sealed Edit;
authorwenzelm
Wed, 02 Sep 2009 21:21:54 +0200
changeset 34693 3e995f100ad2
parent 34692 3c0a8bece8b8
child 34694 51f9011c777b
sealed Edit; Change.edits: plain field, plain list -- no reverse; TheoryView.edits: ListBuffer -- no reverse; misc tuning;
src/Tools/jEdit/src/jedit/TheoryView.scala
src/Tools/jEdit/src/proofdocument/Change.scala
src/Tools/jEdit/src/proofdocument/ProofDocument.scala
--- a/src/Tools/jEdit/src/jedit/TheoryView.scala	Tue Sep 01 21:05:57 2009 +0200
+++ b/src/Tools/jEdit/src/jedit/TheoryView.scala	Wed Sep 02 21:21:54 2009 +0200
@@ -10,6 +10,7 @@
 
 import scala.actors.Actor
 import scala.actors.Actor._
+import scala.collection.mutable
 
 import isabelle.proofdocument.{ProofDocument, Change, Edit, Insert, Remove}
 import isabelle.prover.{Prover, ProverEvents, Command}
@@ -108,14 +109,14 @@
     // changes in buffer must be ignored
     buffer.removeBufferListener(this)
 
-    def apply(c: Change) = c.map {
-      case Insert(start, added) => buffer.insert(start, added)
-      case Remove(start, removed) => buffer.remove(start, removed.length)
+    def apply(change: Change): Unit = change.edits.foreach {
+      case Insert(start, text) => buffer.insert(start, text)
+      case Remove(start, text) => buffer.remove(start, text.length)
     }
 
-    def unapply(c: Change) = c.toList.reverse.map {
-      case Insert(start, added) => buffer.remove(start, added.length)
-      case Remove(start, removed) => buffer.insert(start, removed)
+    def unapply(change: Change): Unit = change.edits.reverse.foreach {
+      case Insert(start, text) => buffer.remove(start, text.length)
+      case Remove(start, text) => buffer.insert(start, text)
     }
 
     // undo/redo changes
@@ -151,36 +152,40 @@
     buffer.addBufferListener(this)
   }
 
+
   /* sending edits to prover */
 
-  private var edits: List[Edit] = Nil
+  private val edits = new mutable.ListBuffer[Edit]   // owned by Swing/AWT thread
 
   private val col_timer = new Timer(300, new ActionListener() {
-    override def actionPerformed(e: ActionEvent) = commit
+    override def actionPerformed(e: ActionEvent) = commit()
   })
 
   col_timer.stop
   col_timer.setRepeats(true)
 
-  private def commit: Unit = synchronized {
+  private def commit() {
+    Swing_Thread.require()
     if (!edits.isEmpty) {
-      val change = new Change(Isabelle.system.id(), Some(current_change), edits)
+      val change = new Change(Isabelle.system.id(), Some(current_change), edits.toList)
       _changes ::= change
       prover ! change
       current_change = change
+      edits.clear
     }
-    edits = Nil
     if (col_timer.isRunning())
       col_timer.stop()
   }
 
   private def delay_commit {
+    Swing_Thread.require()
     if (col_timer.isRunning())
       col_timer.restart()
     else
       col_timer.start()
   }
 
+
   /* BufferListener methods */
 
   override def contentInserted(buffer: JEditBuffer,
@@ -192,14 +197,14 @@
   override def preContentInserted(buffer: JEditBuffer,
     start_line: Int, offset: Int, num_lines: Int, length: Int)
   {
-    edits ::= Insert(offset, buffer.getText(offset, length))
+    edits += Insert(offset, buffer.getText(offset, length))
     delay_commit
   }
 
   override def preContentRemoved(buffer: JEditBuffer,
     start_line: Int, start: Int, num_lines: Int, removed_length: Int)
   {
-    edits ::= Remove(start, buffer.getText(start, removed_length))
+    edits += Remove(start, buffer.getText(start, removed_length))
     delay_commit
   }
 
@@ -211,8 +216,8 @@
 
   /* transforming offsets */
 
-  private def changes_to(doc: ProofDocument) =
-    edits ::: current_change.ancestors(_.id == doc.id).flatten(_.toList)
+  private def changes_to(doc: ProofDocument): List[Edit] =
+    edits.toList ::: List.flatten(current_change.ancestors(_.id == doc.id).map(_.edits))
 
   def from_current(doc: ProofDocument, pos: Int) =
     (pos /: changes_to(doc)) ((p, c) => c from_where p)
@@ -314,9 +319,12 @@
   lazy val change_receiver: Actor = actor {
     loop {
       react {
-        case ProverEvents.Activate =>
-          edits = List(Insert(0, buffer.getText(0, buffer.getLength)))
-          commit
+        case ProverEvents.Activate =>   // FIXME !?
+          Swing_Thread.now {
+            edits.clear
+            edits += Insert(0, buffer.getText(0, buffer.getLength))
+            commit()
+          }
         case c: Command =>
           actor{Isabelle.plugin.command_change.event(c)}
           if(current_document().commands.contains(c))
--- a/src/Tools/jEdit/src/proofdocument/Change.scala	Tue Sep 01 21:05:57 2009 +0200
+++ b/src/Tools/jEdit/src/proofdocument/Change.scala	Wed Sep 02 21:21:54 2009 +0200
@@ -7,41 +7,42 @@
 
 package isabelle.proofdocument
 
-abstract class Edit {
+sealed abstract class Edit
+{
   val start: Int
   def from_where (x: Int): Int //where has x been before applying this edit
   def where_to(x: Int): Int //where will x be when we apply this edit
 }
 
-case class Insert(start: Int, added: String) extends Edit {
+case class Insert(start: Int, text: String) extends Edit
+{
   def from_where(x: Int) =
     if (start > x) x
-    else (x - added.length) max start
+    else (x - text.length) max start
 
   def where_to(x: Int) =
-    if (start <= x) x + added.length else x
+    if (start <= x) x + text.length else x
 }
 
-case class Remove(start: Int, removed: String) extends Edit {
+case class Remove(start: Int, text: String) extends Edit
+{
   def from_where(x: Int) =
-    if (start <= x) x + removed.length else x
+    if (start <= x) x + text.length else x
 
   def where_to(x: Int) =
     if (start > x) x
-    else (x - removed.length) max start
+    else (x - text.length) max start
 }
 // TODO: merge multiple inserts?
 
 class Change(
   val id: String,
   val parent: Option[Change],
-  edits: List[Edit]) extends Iterable[Edit]
+  val edits: List[Edit])
 {
-  override def elements = edits.reverse.elements
-
-  def ancestors(root_p: Change => Boolean): List[Change] =
-    if (root_p(this)) Nil
-    else this :: parent.map(_.ancestors(root_p)).getOrElse(Nil)
+  def ancestors(done: Change => Boolean): List[Change] =
+    if (done(this)) Nil
+    else this :: parent.map(_.ancestors(done)).getOrElse(Nil)
   def ancestors: List[Change] = ancestors(_ => false)
 
   override def toString =
--- a/src/Tools/jEdit/src/proofdocument/ProofDocument.scala	Tue Sep 01 21:05:57 2009 +0200
+++ b/src/Tools/jEdit/src/proofdocument/ProofDocument.scala	Wed Sep 02 21:21:54 2009 +0200
@@ -62,20 +62,20 @@
   def content = Token.string_from_tokens(Nil ++ tokens, token_start)
 
 
+  
   /** token view **/
 
-  def text_changed(c: Change): (ProofDocument, StructureChange)  =
+  def text_changed(change: Change): (ProofDocument, StructureChange) =
   {
     def edit_doc(doc_chgs: (ProofDocument, StructureChange), edit: Edit) = {
       val (doc, chgs) = doc_chgs
-      val (new_doc, chg) = doc.text_edit(edit, c.id)
+      val (new_doc, chg) = doc.text_edit(edit, change.id)
       (new_doc, chgs ++ chg)
     }
-    ((this, Nil: StructureChange) /: c) (edit_doc)
+    ((this, Nil: StructureChange) /: change.edits)(edit_doc)
   }
 
-  def text_edit(e: Edit, id: String):
-    (ProofDocument,StructureChange) =
+  def text_edit(e: Edit, id: String): (ProofDocument,StructureChange) =
   {
     case class TextChange(start: Int, added: String, removed: String)
     val change = e match {