src/Tools/jEdit/src/graph_dockable.scala
changeset 49566 66cbf8bb4693
parent 49557 61988f9df94d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/graph_dockable.scala	Tue Sep 25 22:36:06 2012 +0200
@@ -0,0 +1,131 @@
+/*  Title:      Tools/jEdit/src/graph_dockable.scala
+    Author:     Markus Kaiser, TU Muenchen
+    Author:     Makarius
+
+Dockable window for graphview.
+*/
+
+package isabelle.jedit
+
+
+import isabelle._
+
+import java.awt.BorderLayout
+import javax.swing.JPanel
+
+import scala.actors.Actor._
+
+import org.gjt.sp.jedit.View
+
+
+class Graph_Dockable(view: View, position: String) extends Dockable(view, position)
+{
+  Swing_Thread.require()
+
+
+  /* component state -- owned by Swing thread */
+
+  private val do_update = true  // FIXME
+
+  private var current_snapshot = Document.State.init.snapshot()
+  private var current_state = Command.empty.init_state
+  private var current_graph: XML.Body = Nil
+
+
+  /* GUI components */
+
+  private val graphview = new JPanel
+
+  // FIXME mutable GUI content
+  private def set_graphview(graph: XML.Body)
+  {
+    graphview.removeAll()
+    graphview.setLayout(new BorderLayout)
+    val panel = new isabelle.graphview.Main_Panel(isabelle.graphview.Model.decode_graph(graph))
+    graphview.add(panel.peer, BorderLayout.CENTER)
+  }
+
+  set_graphview(current_graph)
+  set_content(graphview)
+
+
+  private def handle_update(follow: Boolean, restriction: Option[Set[Command]])
+  {
+    Swing_Thread.require()
+
+    val (new_snapshot, new_state) =
+      Document_View(view.getTextArea) match {
+        case Some(doc_view) =>
+          val snapshot = doc_view.model.snapshot()
+          if (follow && !snapshot.is_outdated) {
+            snapshot.node.command_at(doc_view.text_area.getCaretPosition).map(_._1) match {
+              case Some(cmd) =>
+                (snapshot, snapshot.state.command_state(snapshot.version, cmd))
+              case None =>
+                (Document.State.init.snapshot(), Command.empty.init_state)
+            }
+          }
+          else (current_snapshot, current_state)
+        case None => (current_snapshot, current_state)
+      }
+
+    val new_graph =
+      if (!restriction.isDefined || restriction.get.contains(new_state.command)) {
+        new_state.markup.cumulate[Option[XML.Body]](
+          new_state.command.range, None, Some(Set(Isabelle_Markup.GRAPHVIEW)),
+        {
+          case (_, Text.Info(_, XML.Elem(Markup(Isabelle_Markup.GRAPHVIEW, _), graph))) =>
+            Some(graph)
+        }).filter(_.info.isDefined) match {
+          case Text.Info(_, Some(graph)) #:: _ => graph
+          case _ => Nil
+        }
+      }
+      else current_graph
+
+    if (new_graph != current_graph) set_graphview(new_graph)
+
+    current_snapshot = new_snapshot
+    current_state = new_state
+    current_graph = new_graph
+  }
+
+
+  /* main actor */
+
+  private val main_actor = actor {
+    loop {
+      react {
+        case Session.Global_Options =>  // FIXME
+
+        case changed: Session.Commands_Changed =>
+          Swing_Thread.later { handle_update(do_update, Some(changed.commands)) }
+
+        case Session.Caret_Focus =>
+          Swing_Thread.later { handle_update(do_update, None) }
+
+        case bad =>
+          java.lang.System.err.println("Graph_Dockable: ignoring bad message " + bad)
+      }
+    }
+  }
+
+  override def init()
+  {
+    Swing_Thread.require()
+
+    Isabelle.session.global_options += main_actor
+    Isabelle.session.commands_changed += main_actor
+    Isabelle.session.caret_focus += main_actor
+    handle_update(do_update, None)
+  }
+
+  override def exit()
+  {
+    Swing_Thread.require()
+
+    Isabelle.session.global_options -= main_actor
+    Isabelle.session.commands_changed -= main_actor
+    Isabelle.session.caret_focus -= main_actor
+  }
+}