From b86cf1559a8643dd85b586e83743b2fa00cc8c8a Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Mon, 24 Nov 2014 15:06:35 +0100 Subject: [PATCH 01/19] A first manager --- .../io/atal/butterfly/EditorManager.scala | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/main/scala/io/atal/butterfly/EditorManager.scala diff --git a/src/main/scala/io/atal/butterfly/EditorManager.scala b/src/main/scala/io/atal/butterfly/EditorManager.scala new file mode 100644 index 0000000..cf03bcc --- /dev/null +++ b/src/main/scala/io/atal/butterfly/EditorManager.scala @@ -0,0 +1,33 @@ +package io.atal.butterfly + +/** A manager that allow to use multiple editor + * Call function of Editor, and manage the focus upon editors + * Manage the clipboard + */ +class EditorManager { + var _editors: List[Editor] = List() + var _clipboard: Clipboard = new Clipboard() + var _currentEditor: Option[Editor] = None + + def editors: List[Editor] = _editors + + def clipboard: Clipboard = _clipboard + + def currentEditor: Option[Editor] = _currentEditor + + def currentEditor_=(editor: Editor) = _currentEditor = Some(editor) + + /** Open a new Editor + * + * @TODO Add a param files to open a file text + */ + def openEditor: Unit = new Editor() :: editors + + /** Close an Editor + * + * @param editor The editor to close + * @TODO Save the editor + */ + def closeEditor(editor: Editor): Unit = editors == editors.diff(List(editor)) + +} From bfbed41c5204484cc6143176bb9a74424032c89e Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Tue, 25 Nov 2014 15:12:24 +0100 Subject: [PATCH 02/19] Add methods interacting with the current Editor --- .../io/atal/butterfly/EditorManager.scala | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/main/scala/io/atal/butterfly/EditorManager.scala b/src/main/scala/io/atal/butterfly/EditorManager.scala index cf03bcc..d919d18 100644 --- a/src/main/scala/io/atal/butterfly/EditorManager.scala +++ b/src/main/scala/io/atal/butterfly/EditorManager.scala @@ -29,5 +29,43 @@ class EditorManager { * @TODO Save the editor */ def closeEditor(editor: Editor): Unit = editors == editors.diff(List(editor)) + + /** Write text into the current Editor + * + * Call the write method of Editor + * @param text The text to insert + */ + def write(text: String): Unit = _currentEditor match { + case Some(editor) => editor.write(text) + case None => Unit + } + + /** Erase text from the current Editor + * + * Call the erase method of Editor + */ + def erase: Unit = _currentEditor match { + case Some(editor) => editor.erase + case None => Unit + } + + /** Erase all the selections from the current Editor + * + * Call the eraseSelection method from Editor + */ + def eraseSelection: Unit = _currentEditor match { + case Some(editor) => editor.eraseSelection + case None => Unit + } + /** Get contents from the selections of the current Editor + * + * Call the getSelectionContent method from Editor + * @return String The text from the selection (or an empty string if there is no current editor) + */ + def getSelectionContent: String = _currentEditor match { + case Some(editor) => editor.getSelectionContent + case None => "" + } + } From ac594b21fb43f8db9a0157bc308edd2b3793d361 Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Tue, 25 Nov 2014 15:13:00 +0100 Subject: [PATCH 03/19] Corrections --- src/main/scala/io/atal/butterfly/EditorManager.scala | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/scala/io/atal/butterfly/EditorManager.scala b/src/main/scala/io/atal/butterfly/EditorManager.scala index d919d18..755612f 100644 --- a/src/main/scala/io/atal/butterfly/EditorManager.scala +++ b/src/main/scala/io/atal/butterfly/EditorManager.scala @@ -21,14 +21,22 @@ class EditorManager { * * @TODO Add a param files to open a file text */ - def openEditor: Unit = new Editor() :: editors + def openEditor: Unit = { + _editors = new Editor() :: _editors + _currentEditor = Some(_editors.head) + } /** Close an Editor * * @param editor The editor to close * @TODO Save the editor */ - def closeEditor(editor: Editor): Unit = editors == editors.diff(List(editor)) + def closeEditor(editor: Editor): Unit = { + _editors = _editors.diff(List(editor)) + if(_currentEditor == Some(editor)) { + _currentEditor = Some(_editors.head) + } + } /** Write text into the current Editor * From 444b5aec3a44f682530d329999d03fcea49e9c20 Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Tue, 25 Nov 2014 17:34:06 +0100 Subject: [PATCH 04/19] Add some test units --- .../io/atal/butterfly/EditorManagerTest.scala | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/test/scala/io/atal/butterfly/EditorManagerTest.scala diff --git a/src/test/scala/io/atal/butterfly/EditorManagerTest.scala b/src/test/scala/io/atal/butterfly/EditorManagerTest.scala new file mode 100644 index 0000000..04d3f85 --- /dev/null +++ b/src/test/scala/io/atal/butterfly/EditorManagerTest.scala @@ -0,0 +1,55 @@ +package io.atal.butterfly + +import org.scalatest._ +import Matchers._ + +/** EditorManager unit tests + */ +class EditorManagerTest extends FlatSpec { + + "The EditorManager accessor and mutator" should "be as expected" in { + val editorManager = new EditorManager + + assert(editorManager.editors == List()) + assert(editorManager.currentEditor == None) + } + + "The EditorManager openEditor method" should "add a new editor and move the current editor to it" in { + val editorManager = new EditorManager + + editorManager.editors should have length 0 + + editorManager.openEditor + + editorManager.editors should have length 1 + assert(editorManager.currentEditor == Some(editorManager.editors.head)) + } + + "The EditorManager closeEditor method" should "remove the editor and potentially move the current editor" in { + val editorManager = new EditorManager + + editorManager.openEditor + editorManager.openEditor + + editorManager.editors should have length 2 + assert(editorManager.currentEditor == Some(editorManager.editors.head)) + + var old_editors = editorManager.editors + + editorManager.closeEditor(editorManager.editors.head) + assert(editorManager.editors == old_editors.tail) + assert(editorManager.currentEditor == Some(editorManager.editors.head)) + + editorManager.openEditor + + editorManager.editors should have length 2 + assert(editorManager.currentEditor == Some(editorManager.editors.head)) + + old_editors = editorManager.editors + + editorManager.closeEditor(editorManager.editors.tail.head) + assert(editorManager.editors == old_editors.head :: old_editors.tail.tail) + assert(editorManager.currentEditor == Some(editorManager.editors.head)) + } + +} From dfc29a43c8060ac6d01aac0854e2992af0eb48b6 Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Fri, 28 Nov 2014 17:37:51 +0100 Subject: [PATCH 05/19] A usefull method for cursors --- src/main/scala/io/atal/butterfly/Editor.scala | 12 ++++++++++++ src/test/scala/io/atal/butterfly/EditorTest.scala | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/main/scala/io/atal/butterfly/Editor.scala b/src/main/scala/io/atal/butterfly/Editor.scala index 344efcc..3109c67 100644 --- a/src/main/scala/io/atal/butterfly/Editor.scala +++ b/src/main/scala/io/atal/butterfly/Editor.scala @@ -109,6 +109,18 @@ class Editor(var buffer: Buffer = new Buffer("")) { /** Clear all selections */ def clearSelection: Unit = selections = List() + + + /** Return the position of the cursor in the whole string + * + * @param cursor The cursor that we want + * @retutrn The position in the buffer + */ + def getIndexPosition(cursor: Cursor): Int = cursor.position match { + case (0, y) => y + case (x, 0) => buffer.lines(x-1).length + 1 + getIndexPosition(new Cursor(x-1, 0)) + case (x, y) => y + getIndexPosition(new Cursor(x, 0)) + } /** Move up all cursors * diff --git a/src/test/scala/io/atal/butterfly/EditorTest.scala b/src/test/scala/io/atal/butterfly/EditorTest.scala index e0e4ca0..0bb612b 100644 --- a/src/test/scala/io/atal/butterfly/EditorTest.scala +++ b/src/test/scala/io/atal/butterfly/EditorTest.scala @@ -105,6 +105,16 @@ class EditorTest extends FlatSpec { editor.selections should have length 0 } + + "The Editor getIndexPosition method" should "actually return the index position of the cursor" in { + val editor = new Editor + val cursor = new Cursor((1,3)) + + editor.buffer.content = "Hello\nthe world" + + assert(editor.getIndexPosition(cursor) == 9) + + } "The Editor write method" should "write the given text at all cursors position" in { val editor = new Editor From 79fae7b1c0a5674ff581c2bf15473a4b8518d58a Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Fri, 28 Nov 2014 18:27:35 +0100 Subject: [PATCH 06/19] Corrections --- src/main/scala/io/atal/butterfly/Buffer.scala | 2 +- src/main/scala/io/atal/butterfly/Editor.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/io/atal/butterfly/Buffer.scala b/src/main/scala/io/atal/butterfly/Buffer.scala index c50f7c2..90d1d34 100644 --- a/src/main/scala/io/atal/butterfly/Buffer.scala +++ b/src/main/scala/io/atal/butterfly/Buffer.scala @@ -10,7 +10,7 @@ class Buffer(var content: String) { /** Return the content as an array */ - def lines: Array[String] = content.split("\n") + def lines: Array[String] = content.split("\n", -1) /** Return a selected substring in the buffer * diff --git a/src/main/scala/io/atal/butterfly/Editor.scala b/src/main/scala/io/atal/butterfly/Editor.scala index 3109c67..c513f82 100644 --- a/src/main/scala/io/atal/butterfly/Editor.scala +++ b/src/main/scala/io/atal/butterfly/Editor.scala @@ -25,7 +25,7 @@ class Editor(var buffer: Buffer = new Buffer("")) { def write(text: String): Unit = { for (cursor <- cursors) { buffer.insert(text, cursor.position) - cursor.moveRight(text.length) + moveCursorRight(cursor, text.length) } } From fb84baea27db1ff7ffff331c68485a2a7fdcf3df Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Mon, 17 Nov 2014 13:38:12 +0100 Subject: [PATCH 07/19] Add the dependencies for scala-swing --- build.sbt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.sbt b/build.sbt index 22f7e97..0c2d9b1 100644 --- a/build.sbt +++ b/build.sbt @@ -7,3 +7,5 @@ organization := "io.atal" scalaVersion := "2.11.4" libraryDependencies += "org.scalatest" % "scalatest_2.11" % "2.2.1" % "test" + +libraryDependencies += "org.scala-lang" % "scala-swing" % "2.11+" From c0c27509e80ab3e30c0edd9cc127b04192165e0a Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Thu, 20 Nov 2014 12:07:21 +0100 Subject: [PATCH 08/19] Add a simple interface --- .../scala/io/atal/butterfly/Interface.scala | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/main/scala/io/atal/butterfly/Interface.scala diff --git a/src/main/scala/io/atal/butterfly/Interface.scala b/src/main/scala/io/atal/butterfly/Interface.scala new file mode 100644 index 0000000..974bf08 --- /dev/null +++ b/src/main/scala/io/atal/butterfly/Interface.scala @@ -0,0 +1,51 @@ +package io.atal.butterfly + +import scala.swing._ +import scala.swing.event._ + +/** + * A simple swing demo. + */ +object HelloWorld extends SimpleSwingApplication { + def top = new MainFrame { + title = "Hello, World!" + + object editor extends Label { + var buffer = new Buffer("") + var _cursor = 0 + + text = buffer.toString() + preferredSize = new Dimension(1000,500) + + listenTo(button) + reactions += { + case ButtonClicked(button) => + if(input.text != "") + { + buffer.insert(input.text, _cursor) + _cursor += input.text.length + text = buffer.toString() + input.text = "" + } + } + } + + object button extends Button { + text = "Insert" + } + + val input = new TextField(100) + + contents = new BorderPanel { + add(editor, BorderPanel.Position.North) + add(input, BorderPanel.Position.West) + add(button, BorderPanel.Position.East) + border = Swing.EmptyBorder(10, 10, 10, 10) + + focusable = true + requestFocus + } + + } +} + From 6c2103d196fe3fefe23335082cd2afa9406278fb Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Mon, 24 Nov 2014 14:43:30 +0100 Subject: [PATCH 09/19] A little better interface --- src/main/scala/io/atal/butterfly/Interface.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/scala/io/atal/butterfly/Interface.scala b/src/main/scala/io/atal/butterfly/Interface.scala index 974bf08..963906c 100644 --- a/src/main/scala/io/atal/butterfly/Interface.scala +++ b/src/main/scala/io/atal/butterfly/Interface.scala @@ -24,7 +24,7 @@ object HelloWorld extends SimpleSwingApplication { { buffer.insert(input.text, _cursor) _cursor += input.text.length - text = buffer.toString() + text = bufferToLabel(buffer.toString()) input.text = "" } } @@ -34,7 +34,7 @@ object HelloWorld extends SimpleSwingApplication { text = "Insert" } - val input = new TextField(100) + val input = new TextArea(50,100) contents = new BorderPanel { add(editor, BorderPanel.Position.North) @@ -47,5 +47,7 @@ object HelloWorld extends SimpleSwingApplication { } } + + def bufferToLabel(s: String) : String = return "" + s.replaceAll("\n", "
") + "" } From 55bf5b0d5490d37ddc420e4759fa7fd0d10b8506 Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Tue, 25 Nov 2014 23:12:37 +0100 Subject: [PATCH 10/19] Refacting interface, using the EditorManager --- .../scala/io/atal/butterfly/Interface.scala | 51 ++++++++++--------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/src/main/scala/io/atal/butterfly/Interface.scala b/src/main/scala/io/atal/butterfly/Interface.scala index 963906c..04fdd6b 100644 --- a/src/main/scala/io/atal/butterfly/Interface.scala +++ b/src/main/scala/io/atal/butterfly/Interface.scala @@ -10,44 +10,45 @@ object HelloWorld extends SimpleSwingApplication { def top = new MainFrame { title = "Hello, World!" + var editorManager = new EditorManager + editorManager.openEditor + + var current: Editor = editorManager.currentEditor.get + object editor extends Label { - var buffer = new Buffer("") - var _cursor = 0 - - text = buffer.toString() + text = current.buffer.content preferredSize = new Dimension(1000,500) + + focusable = true + requestFocus - listenTo(button) + listenTo(keys) reactions += { - case ButtonClicked(button) => - if(input.text != "") - { - buffer.insert(input.text, _cursor) - _cursor += input.text.length - text = bufferToLabel(buffer.toString()) - input.text = "" - } + case KeyPressed(_, Key.BackSpace, _, _) => { + current.erase + updateLabel + } + + case KeyPressed(_, Key.A, _, _) => keyChar("a") } } - object button extends Button { - text = "Insert" - } - - val input = new TextArea(50,100) - - contents = new BorderPanel { - add(editor, BorderPanel.Position.North) - add(input, BorderPanel.Position.West) - add(button, BorderPanel.Position.East) + contents = new FlowPanel { + contents.append(editor) border = Swing.EmptyBorder(10, 10, 10, 10) - focusable = true - requestFocus } + + def keyChar(char: String): Unit = { + current.write(char) + updateLabel + } + + def updateLabel: Unit = editor.text = bufferToLabel(current.buffer.content) } def bufferToLabel(s: String) : String = return "" + s.replaceAll("\n", "
") + "" + } From dd8491f1c29d8c7de137598b68fb63b89c9bbb7b Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Wed, 26 Nov 2014 00:00:36 +0100 Subject: [PATCH 11/19] Add letters --- .../scala/io/atal/butterfly/Interface.scala | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/main/scala/io/atal/butterfly/Interface.scala b/src/main/scala/io/atal/butterfly/Interface.scala index 04fdd6b..1088c37 100644 --- a/src/main/scala/io/atal/butterfly/Interface.scala +++ b/src/main/scala/io/atal/butterfly/Interface.scala @@ -30,6 +30,31 @@ object HelloWorld extends SimpleSwingApplication { } case KeyPressed(_, Key.A, _, _) => keyChar("a") + case KeyPressed(_, Key.B, _, _) => keyChar("b") + case KeyPressed(_, Key.C, _, _) => keyChar("c") + case KeyPressed(_, Key.D, _, _) => keyChar("d") + case KeyPressed(_, Key.E, _, _) => keyChar("e") + case KeyPressed(_, Key.F, _, _) => keyChar("f") + case KeyPressed(_, Key.G, _, _) => keyChar("g") + case KeyPressed(_, Key.H, _, _) => keyChar("h") + case KeyPressed(_, Key.I, _, _) => keyChar("i") + case KeyPressed(_, Key.J, _, _) => keyChar("j") + case KeyPressed(_, Key.K, _, _) => keyChar("k") + case KeyPressed(_, Key.L, _, _) => keyChar("l") + case KeyPressed(_, Key.M, _, _) => keyChar("m") + case KeyPressed(_, Key.N, _, _) => keyChar("n") + case KeyPressed(_, Key.O, _, _) => keyChar("o") + case KeyPressed(_, Key.P, _, _) => keyChar("p") + case KeyPressed(_, Key.Q, _, _) => keyChar("q") + case KeyPressed(_, Key.R, _, _) => keyChar("r") + case KeyPressed(_, Key.S, _, _) => keyChar("s") + case KeyPressed(_, Key.T, _, _) => keyChar("t") + case KeyPressed(_, Key.U, _, _) => keyChar("u") + case KeyPressed(_, Key.V, _, _) => keyChar("v") + case KeyPressed(_, Key.W, _, _) => keyChar("w") + case KeyPressed(_, Key.X, _, _) => keyChar("x") + case KeyPressed(_, Key.Y, _, _) => keyChar("y") + case KeyPressed(_, Key.Z, _, _) => keyChar("z") } } From 17dd5ea2a7d8762df658b530c5470419c6befa81 Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Wed, 26 Nov 2014 00:03:38 +0100 Subject: [PATCH 12/19] Add upper case events --- src/main/scala/io/atal/butterfly/Interface.scala | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/scala/io/atal/butterfly/Interface.scala b/src/main/scala/io/atal/butterfly/Interface.scala index 1088c37..620c1b9 100644 --- a/src/main/scala/io/atal/butterfly/Interface.scala +++ b/src/main/scala/io/atal/butterfly/Interface.scala @@ -14,6 +14,8 @@ object HelloWorld extends SimpleSwingApplication { editorManager.openEditor var current: Editor = editorManager.currentEditor.get + var isShift: Boolean = false + var isCapsLock: Boolean = false object editor extends Label { text = current.buffer.content @@ -29,6 +31,16 @@ object HelloWorld extends SimpleSwingApplication { updateLabel } + case KeyPressed(_, Key.Shift, _, _) => isShift = true + case KeyReleased(_, Key.Shift, _, _) => isShift = false + + case KeyPressed(_, Key.CapsLock, _, _) => { + if(isCapsLock) + isCapsLock = false + else + isCapsLock = true + } + case KeyPressed(_, Key.A, _, _) => keyChar("a") case KeyPressed(_, Key.B, _, _) => keyChar("b") case KeyPressed(_, Key.C, _, _) => keyChar("c") From b44ace2d57d0cead47833dd5c5f9801a87910449 Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Wed, 26 Nov 2014 00:09:48 +0100 Subject: [PATCH 13/19] Can now write upper case letters --- .../scala/io/atal/butterfly/Interface.scala | 60 ++++++++++--------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/src/main/scala/io/atal/butterfly/Interface.scala b/src/main/scala/io/atal/butterfly/Interface.scala index 620c1b9..6cc43ef 100644 --- a/src/main/scala/io/atal/butterfly/Interface.scala +++ b/src/main/scala/io/atal/butterfly/Interface.scala @@ -41,32 +41,32 @@ object HelloWorld extends SimpleSwingApplication { isCapsLock = true } - case KeyPressed(_, Key.A, _, _) => keyChar("a") - case KeyPressed(_, Key.B, _, _) => keyChar("b") - case KeyPressed(_, Key.C, _, _) => keyChar("c") - case KeyPressed(_, Key.D, _, _) => keyChar("d") - case KeyPressed(_, Key.E, _, _) => keyChar("e") - case KeyPressed(_, Key.F, _, _) => keyChar("f") - case KeyPressed(_, Key.G, _, _) => keyChar("g") - case KeyPressed(_, Key.H, _, _) => keyChar("h") - case KeyPressed(_, Key.I, _, _) => keyChar("i") - case KeyPressed(_, Key.J, _, _) => keyChar("j") - case KeyPressed(_, Key.K, _, _) => keyChar("k") - case KeyPressed(_, Key.L, _, _) => keyChar("l") - case KeyPressed(_, Key.M, _, _) => keyChar("m") - case KeyPressed(_, Key.N, _, _) => keyChar("n") - case KeyPressed(_, Key.O, _, _) => keyChar("o") - case KeyPressed(_, Key.P, _, _) => keyChar("p") - case KeyPressed(_, Key.Q, _, _) => keyChar("q") - case KeyPressed(_, Key.R, _, _) => keyChar("r") - case KeyPressed(_, Key.S, _, _) => keyChar("s") - case KeyPressed(_, Key.T, _, _) => keyChar("t") - case KeyPressed(_, Key.U, _, _) => keyChar("u") - case KeyPressed(_, Key.V, _, _) => keyChar("v") - case KeyPressed(_, Key.W, _, _) => keyChar("w") - case KeyPressed(_, Key.X, _, _) => keyChar("x") - case KeyPressed(_, Key.Y, _, _) => keyChar("y") - case KeyPressed(_, Key.Z, _, _) => keyChar("z") + case KeyPressed(_, Key.A, _, _) => keyChar("a", "A") + case KeyPressed(_, Key.B, _, _) => keyChar("b", "B") + case KeyPressed(_, Key.C, _, _) => keyChar("c", "C") + case KeyPressed(_, Key.D, _, _) => keyChar("d", "D") + case KeyPressed(_, Key.E, _, _) => keyChar("e", "E") + case KeyPressed(_, Key.F, _, _) => keyChar("f", "F") + case KeyPressed(_, Key.G, _, _) => keyChar("g", "G") + case KeyPressed(_, Key.H, _, _) => keyChar("h", "H") + case KeyPressed(_, Key.I, _, _) => keyChar("i", "I") + case KeyPressed(_, Key.J, _, _) => keyChar("j", "J") + case KeyPressed(_, Key.K, _, _) => keyChar("k", "K") + case KeyPressed(_, Key.L, _, _) => keyChar("l", "L") + case KeyPressed(_, Key.M, _, _) => keyChar("m", "M") + case KeyPressed(_, Key.N, _, _) => keyChar("n", "N") + case KeyPressed(_, Key.O, _, _) => keyChar("o", "O") + case KeyPressed(_, Key.P, _, _) => keyChar("p", "P") + case KeyPressed(_, Key.Q, _, _) => keyChar("q", "Q") + case KeyPressed(_, Key.R, _, _) => keyChar("r", "R") + case KeyPressed(_, Key.S, _, _) => keyChar("s", "S") + case KeyPressed(_, Key.T, _, _) => keyChar("t", "T") + case KeyPressed(_, Key.U, _, _) => keyChar("u", "U") + case KeyPressed(_, Key.V, _, _) => keyChar("v", "V") + case KeyPressed(_, Key.W, _, _) => keyChar("w", "W") + case KeyPressed(_, Key.X, _, _) => keyChar("x", "X") + case KeyPressed(_, Key.Y, _, _) => keyChar("y", "Y") + case KeyPressed(_, Key.Z, _, _) => keyChar("z", "Z") } } @@ -77,8 +77,12 @@ object HelloWorld extends SimpleSwingApplication { } - def keyChar(char: String): Unit = { - current.write(char) + def keyChar(lowerChar: String, upperChar: String): Unit = { + if((isShift && !isCapsLock) || (isCapsLock && !isShift)) + current.write(upperChar) + else + current.write(lowerChar) + updateLabel } From 289d930fc0fc8af62697cf6b5982ca80fbdd9828 Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Wed, 26 Nov 2014 00:38:01 +0100 Subject: [PATCH 14/19] Add numbers --- .../scala/io/atal/butterfly/Interface.scala | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/main/scala/io/atal/butterfly/Interface.scala b/src/main/scala/io/atal/butterfly/Interface.scala index 6cc43ef..1b6385d 100644 --- a/src/main/scala/io/atal/butterfly/Interface.scala +++ b/src/main/scala/io/atal/butterfly/Interface.scala @@ -67,6 +67,19 @@ object HelloWorld extends SimpleSwingApplication { case KeyPressed(_, Key.X, _, _) => keyChar("x", "X") case KeyPressed(_, Key.Y, _, _) => keyChar("y", "Y") case KeyPressed(_, Key.Z, _, _) => keyChar("z", "Z") + + case KeyPressed(_, Key.Ampersand, _, _) => keyOther("&", "1") + //case KeyPressed(_, Key.Key2, _, _) => keyCapsSpec("é", "2", "É") Code d'erreur + case KeyPressed(_, Key.Quotedbl, _, _) => keyOther("\"", "3") + case KeyPressed(_, Key.Quote, _, _) => keyOther("'", "4") + case KeyPressed(_, Key.LeftParenthesis, _, _) => keyOther("(", "5") + case KeyPressed(_, Key.Minus, _, _) => keyOther("-", "6") + //case KeyPressed(_, Key.Key7, _, _) => keyCapsSpec("è", "7", "È") Code d'erreur + case KeyPressed(_, Key.Underscore, _, _) => keyOther("_", "8") + //case KeyPressed(_, Key.Key9, _, _) => keyCapsSpec("ç", "9", "Ç") Code d'erreur + //case KeyPressed(_, Key.Key0, _, _) => keyCapsSpec("à", "0", "À") Code d'erreur + case KeyPressed(_, Key.RightParenthesis, _, _) => keyOther(")", "°") + case KeyPressed(_, Key.Equals, _, _) => keyOther("=", "+") } } @@ -85,7 +98,27 @@ object HelloWorld extends SimpleSwingApplication { updateLabel } + + def keyCapsSpec(lower: String, shift: String, capsLock: String): Unit = { + if(isShift) + current.write(shift) + else if(isCapsLock) + current.write(capsLock) + else + current.write(lower) + updateLabel + } + + def keyOther(lower: String, shift: String): Unit = { + if(isShift) + current.write(shift) + else + current.write(lower) + + updateLabel + } + def updateLabel: Unit = editor.text = bufferToLabel(current.buffer.content) } From 2859f1a1432ca797ec691407268607c16386d260 Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Wed, 26 Nov 2014 12:17:17 +0100 Subject: [PATCH 15/19] Add more key --- .../scala/io/atal/butterfly/Interface.scala | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/main/scala/io/atal/butterfly/Interface.scala b/src/main/scala/io/atal/butterfly/Interface.scala index 1b6385d..e5c87f8 100644 --- a/src/main/scala/io/atal/butterfly/Interface.scala +++ b/src/main/scala/io/atal/butterfly/Interface.scala @@ -80,6 +80,26 @@ object HelloWorld extends SimpleSwingApplication { //case KeyPressed(_, Key.Key0, _, _) => keyCapsSpec("à", "0", "À") Code d'erreur case KeyPressed(_, Key.RightParenthesis, _, _) => keyOther(")", "°") case KeyPressed(_, Key.Equals, _, _) => keyOther("=", "+") + + case KeyPressed(_, Key.Enter, _, _) => { + current.write("\n") + updateLabel + } + + case KeyPressed(_, Key.Space, _, _) => { + current.write(" ") + updateLabel + } + + case KeyPressed(_, Key.Comma, _, _) => keyOther(",", "?") + case KeyPressed(_, Key.Semicolon, _, _) => keyOther(";", ".") + case KeyPressed(_, Key.Colon, _, _) => keyOther(":", "/") + case KeyPressed(_, Key.ExclamationMark, _, _) => keyOther("!", "/") + case KeyPressed(_, Key.Asterisk, _, _) => keyOther("*", "µ") + //case KeyPressed(_, Key.Circumflex, _, _) => keyOther("^", "¨") Erreur, ne fait rien + case KeyPressed(_, Key.Dollar, _, _) => keyOther("$", "£") + + //Touche "ù" Code d'erreur } } From adb10328249eb4dbc5d7bab0c07f4f8885a7d721 Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Thu, 27 Nov 2014 22:13:02 +0100 Subject: [PATCH 16/19] Magical match. All key is recognized (Thank you Damien) --- .../scala/io/atal/butterfly/Interface.scala | 115 +++--------------- 1 file changed, 16 insertions(+), 99 deletions(-) diff --git a/src/main/scala/io/atal/butterfly/Interface.scala b/src/main/scala/io/atal/butterfly/Interface.scala index e5c87f8..7e9659f 100644 --- a/src/main/scala/io/atal/butterfly/Interface.scala +++ b/src/main/scala/io/atal/butterfly/Interface.scala @@ -14,8 +14,7 @@ object HelloWorld extends SimpleSwingApplication { editorManager.openEditor var current: Editor = editorManager.currentEditor.get - var isShift: Boolean = false - var isCapsLock: Boolean = false + var isSpec = false object editor extends Label { text = current.buffer.content @@ -26,80 +25,27 @@ object HelloWorld extends SimpleSwingApplication { listenTo(keys) reactions += { + /** + * KeyPressed and KeyTyped are too different event, both sent everytime. + * KeyPressed allow to do any action for a key (those which are non buguy (all accents)), for exemple erase for backspace + * KeyTyped allow to capture the character generate with a key (taking account shift, alt, ...) => no buguy accent, but buguy char for BackSpace + * It doesn't recognize a key, so no filter :( + */ + case KeyPressed(_, Key.BackSpace, _, _) => { - current.erase + isSpec = true + //current.erase <- En commentaire en attendant le merge de la correction (soon) updateLabel } - case KeyPressed(_, Key.Shift, _, _) => isShift = true - case KeyReleased(_, Key.Shift, _, _) => isShift = false + case KeyPressed(_, x, _, _) => isSpec = false //Allow for non-specified KeyPressed (like Key.BackSpace) to be match with KeyTyped. It's ugly. Better way ? - case KeyPressed(_, Key.CapsLock, _, _) => { - if(isCapsLock) - isCapsLock = false - else - isCapsLock = true + case KeyTyped(_, y, _, _) => { + if(!isSpec) { + current.write(y.toString) + updateLabel + } } - - case KeyPressed(_, Key.A, _, _) => keyChar("a", "A") - case KeyPressed(_, Key.B, _, _) => keyChar("b", "B") - case KeyPressed(_, Key.C, _, _) => keyChar("c", "C") - case KeyPressed(_, Key.D, _, _) => keyChar("d", "D") - case KeyPressed(_, Key.E, _, _) => keyChar("e", "E") - case KeyPressed(_, Key.F, _, _) => keyChar("f", "F") - case KeyPressed(_, Key.G, _, _) => keyChar("g", "G") - case KeyPressed(_, Key.H, _, _) => keyChar("h", "H") - case KeyPressed(_, Key.I, _, _) => keyChar("i", "I") - case KeyPressed(_, Key.J, _, _) => keyChar("j", "J") - case KeyPressed(_, Key.K, _, _) => keyChar("k", "K") - case KeyPressed(_, Key.L, _, _) => keyChar("l", "L") - case KeyPressed(_, Key.M, _, _) => keyChar("m", "M") - case KeyPressed(_, Key.N, _, _) => keyChar("n", "N") - case KeyPressed(_, Key.O, _, _) => keyChar("o", "O") - case KeyPressed(_, Key.P, _, _) => keyChar("p", "P") - case KeyPressed(_, Key.Q, _, _) => keyChar("q", "Q") - case KeyPressed(_, Key.R, _, _) => keyChar("r", "R") - case KeyPressed(_, Key.S, _, _) => keyChar("s", "S") - case KeyPressed(_, Key.T, _, _) => keyChar("t", "T") - case KeyPressed(_, Key.U, _, _) => keyChar("u", "U") - case KeyPressed(_, Key.V, _, _) => keyChar("v", "V") - case KeyPressed(_, Key.W, _, _) => keyChar("w", "W") - case KeyPressed(_, Key.X, _, _) => keyChar("x", "X") - case KeyPressed(_, Key.Y, _, _) => keyChar("y", "Y") - case KeyPressed(_, Key.Z, _, _) => keyChar("z", "Z") - - case KeyPressed(_, Key.Ampersand, _, _) => keyOther("&", "1") - //case KeyPressed(_, Key.Key2, _, _) => keyCapsSpec("é", "2", "É") Code d'erreur - case KeyPressed(_, Key.Quotedbl, _, _) => keyOther("\"", "3") - case KeyPressed(_, Key.Quote, _, _) => keyOther("'", "4") - case KeyPressed(_, Key.LeftParenthesis, _, _) => keyOther("(", "5") - case KeyPressed(_, Key.Minus, _, _) => keyOther("-", "6") - //case KeyPressed(_, Key.Key7, _, _) => keyCapsSpec("è", "7", "È") Code d'erreur - case KeyPressed(_, Key.Underscore, _, _) => keyOther("_", "8") - //case KeyPressed(_, Key.Key9, _, _) => keyCapsSpec("ç", "9", "Ç") Code d'erreur - //case KeyPressed(_, Key.Key0, _, _) => keyCapsSpec("à", "0", "À") Code d'erreur - case KeyPressed(_, Key.RightParenthesis, _, _) => keyOther(")", "°") - case KeyPressed(_, Key.Equals, _, _) => keyOther("=", "+") - - case KeyPressed(_, Key.Enter, _, _) => { - current.write("\n") - updateLabel - } - - case KeyPressed(_, Key.Space, _, _) => { - current.write(" ") - updateLabel - } - - case KeyPressed(_, Key.Comma, _, _) => keyOther(",", "?") - case KeyPressed(_, Key.Semicolon, _, _) => keyOther(";", ".") - case KeyPressed(_, Key.Colon, _, _) => keyOther(":", "/") - case KeyPressed(_, Key.ExclamationMark, _, _) => keyOther("!", "/") - case KeyPressed(_, Key.Asterisk, _, _) => keyOther("*", "µ") - //case KeyPressed(_, Key.Circumflex, _, _) => keyOther("^", "¨") Erreur, ne fait rien - case KeyPressed(_, Key.Dollar, _, _) => keyOther("$", "£") - - //Touche "ù" Code d'erreur } } @@ -107,36 +53,7 @@ object HelloWorld extends SimpleSwingApplication { contents.append(editor) border = Swing.EmptyBorder(10, 10, 10, 10) - } - - - def keyChar(lowerChar: String, upperChar: String): Unit = { - if((isShift && !isCapsLock) || (isCapsLock && !isShift)) - current.write(upperChar) - else - current.write(lowerChar) - - updateLabel - } - def keyCapsSpec(lower: String, shift: String, capsLock: String): Unit = { - if(isShift) - current.write(shift) - else if(isCapsLock) - current.write(capsLock) - else - current.write(lower) - - updateLabel - } - - def keyOther(lower: String, shift: String): Unit = { - if(isShift) - current.write(shift) - else - current.write(lower) - - updateLabel } def updateLabel: Unit = editor.text = bufferToLabel(current.buffer.content) From a873fe3bded69b14fdc52c88d15ef0ea41c324dc Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Fri, 28 Nov 2014 15:48:19 +0100 Subject: [PATCH 17/19] Erase is working ! --- src/main/scala/io/atal/butterfly/Interface.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/io/atal/butterfly/Interface.scala b/src/main/scala/io/atal/butterfly/Interface.scala index 7e9659f..d45b296 100644 --- a/src/main/scala/io/atal/butterfly/Interface.scala +++ b/src/main/scala/io/atal/butterfly/Interface.scala @@ -34,7 +34,7 @@ object HelloWorld extends SimpleSwingApplication { case KeyPressed(_, Key.BackSpace, _, _) => { isSpec = true - //current.erase <- En commentaire en attendant le merge de la correction (soon) + current.erase updateLabel } From 76a44b90553a1d5008c897af3f5b3cc5142c4677 Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Fri, 28 Nov 2014 17:23:35 +0100 Subject: [PATCH 18/19] Now we have a cursor (only one) --- .../scala/io/atal/butterfly/Interface.scala | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/main/scala/io/atal/butterfly/Interface.scala b/src/main/scala/io/atal/butterfly/Interface.scala index d45b296..87d02bc 100644 --- a/src/main/scala/io/atal/butterfly/Interface.scala +++ b/src/main/scala/io/atal/butterfly/Interface.scala @@ -16,10 +16,13 @@ object HelloWorld extends SimpleSwingApplication { var current: Editor = editorManager.currentEditor.get var isSpec = false - object editor extends Label { + object editor extends EditorPane { text = current.buffer.content preferredSize = new Dimension(1000,500) + editable = false + caret.visible = true + focusable = true requestFocus @@ -38,6 +41,16 @@ object HelloWorld extends SimpleSwingApplication { updateLabel } + case KeyPressed(_, Key.Left, _, _) => { + isSpec = true + current.moveCursorsLeft() + } + + case KeyPressed(_, Key.Right, _, _) => { + isSpec = true + current.moveCursorsRight() + } + case KeyPressed(_, x, _, _) => isSpec = false //Allow for non-specified KeyPressed (like Key.BackSpace) to be match with KeyTyped. It's ugly. Better way ? case KeyTyped(_, y, _, _) => { @@ -56,10 +69,11 @@ object HelloWorld extends SimpleSwingApplication { } - def updateLabel: Unit = editor.text = bufferToLabel(current.buffer.content) + def updateLabel: Unit = { + editor.text = current.buffer.content + editor.caret.position = current.getIndexPosition(current.cursors.head) + } } - - def bufferToLabel(s: String) : String = return "" + s.replaceAll("\n", "
") + "" } From 575f42a3b40d4bdc5fb00ce93e4ad56baeb89f55 Mon Sep 17 00:00:00 2001 From: Matthieu-Riou Date: Sat, 29 Nov 2014 00:20:05 +0100 Subject: [PATCH 19/19] Add up and down moves --- src/main/scala/io/atal/butterfly/Interface.scala | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/scala/io/atal/butterfly/Interface.scala b/src/main/scala/io/atal/butterfly/Interface.scala index 87d02bc..12f3471 100644 --- a/src/main/scala/io/atal/butterfly/Interface.scala +++ b/src/main/scala/io/atal/butterfly/Interface.scala @@ -51,6 +51,16 @@ object HelloWorld extends SimpleSwingApplication { current.moveCursorsRight() } + case KeyPressed(_, Key.Up, _, _) => { + isSpec = true + current.moveCursorsUp() + } + + case KeyPressed(_, Key.Down, _, _) => { + isSpec = true + current.moveCursorsDown() + } + case KeyPressed(_, x, _, _) => isSpec = false //Allow for non-specified KeyPressed (like Key.BackSpace) to be match with KeyTyped. It's ugly. Better way ? case KeyTyped(_, y, _, _) => {