| author | wenzelm | 
| Wed, 21 Mar 2012 23:26:35 +0100 | |
| changeset 47069 | 451fc10a81f3 | 
| parent 46712 | 8650d9a95736 | 
| child 47539 | 436ae5ea4f80 | 
| permissions | -rw-r--r-- | 
| 38479 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 wenzelm parents: 
38478diff
changeset | 1 | /* Title: Pure/PIDE/markup_tree.scala | 
| 45673 
cd41e3903fbf
separate compilation of PIDE vs. Pure sources, which enables independent Scala library;
 wenzelm parents: 
45667diff
changeset | 2 | Module: PIDE | 
| 36676 | 3 | Author: Fabian Immler, TU Munich | 
| 4 | Author: Makarius | |
| 5 | ||
| 38479 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 wenzelm parents: 
38478diff
changeset | 6 | Markup trees over nested / non-overlapping text ranges. | 
| 36676 | 7 | */ | 
| 34393 | 8 | |
| 34871 
e596a0b71f3c
incorporate "proofdocument" part into main Isabelle/Pure.jar -- except for html_panel.scala, which depends on external library (Lobo/Cobra browser);
 wenzelm parents: 
34760diff
changeset | 9 | package isabelle | 
| 34393 | 10 | |
| 43520 
cec9b95fa35d
explicit import java.lang.System to prevent odd scope problems;
 wenzelm parents: 
39178diff
changeset | 11 | import java.lang.System | 
| 34701 
80b0add08eef
IsabelleSideKickParser: incorporate former MarkupNode.markup2default_node, observe stopped flag;
 wenzelm parents: 
34676diff
changeset | 12 | import javax.swing.tree.DefaultMutableTreeNode | 
| 
80b0add08eef
IsabelleSideKickParser: incorporate former MarkupNode.markup2default_node, observe stopped flag;
 wenzelm parents: 
34676diff
changeset | 13 | |
| 38479 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 wenzelm parents: 
38478diff
changeset | 14 | import scala.collection.immutable.SortedMap | 
| 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 wenzelm parents: 
38478diff
changeset | 15 | |
| 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 wenzelm parents: 
38478diff
changeset | 16 | |
| 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 wenzelm parents: 
38478diff
changeset | 17 | object Markup_Tree | 
| 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 wenzelm parents: 
38478diff
changeset | 18 | {
 | 
| 45456 | 19 | val empty: Markup_Tree = new Markup_Tree(Branches.empty) | 
| 38479 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 wenzelm parents: 
38478diff
changeset | 20 | |
| 45473 | 21 | object Entry | 
| 22 |   {
 | |
| 23 | def apply(markup: Text.Markup, subtree: Markup_Tree): Entry = | |
| 45474 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 24 | Entry(markup.range, List(markup.info), Set(markup.info.markup.name), subtree) | 
| 45473 | 25 | } | 
| 26 | ||
| 45474 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 27 | sealed case class Entry( | 
| 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 28 | range: Text.Range, | 
| 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 29 | rev_markup: List[XML.Elem], | 
| 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 30 | elements: Set[String], | 
| 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 31 | subtree: Markup_Tree) | 
| 45469 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 32 |   {
 | 
| 45474 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 33 | def + (info: XML.Elem): Entry = | 
| 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 34 | if (elements(info.markup.name)) copy(rev_markup = info :: rev_markup) | 
| 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 35 | else copy(rev_markup = info :: rev_markup, elements = elements + info.markup.name) | 
| 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 36 | |
| 45470 | 37 | def markup: List[XML.Elem] = rev_markup.reverse | 
| 45469 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 38 | } | 
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 39 | |
| 38479 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 wenzelm parents: 
38478diff
changeset | 40 | object Branches | 
| 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 wenzelm parents: 
38478diff
changeset | 41 |   {
 | 
| 38578 | 42 | type T = SortedMap[Text.Range, Entry] | 
| 45456 | 43 | val empty: T = SortedMap.empty(Text.Range.Ordering) | 
| 38479 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 wenzelm parents: 
38478diff
changeset | 44 | } | 
| 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 wenzelm parents: 
38478diff
changeset | 45 | } | 
| 34554 
7dc6c231da40
abs. stops, markup nodes depend on doc-version;
 immler@in.tum.de parents: 
34517diff
changeset | 46 | |
| 34393 | 47 | |
| 46712 | 48 | final class Markup_Tree private(branches: Markup_Tree.Branches.T) | 
| 34717 
3f32e08bbb6c
sidekick root data: set buffer length to avoid crash of initial caret move;
 wenzelm parents: 
34708diff
changeset | 49 | {
 | 
| 45469 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 50 | private def this(branches: Markup_Tree.Branches.T, entry: Markup_Tree.Entry) = | 
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 51 | this(branches + (entry.range -> entry)) | 
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 52 | |
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 53 | |
| 38479 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 wenzelm parents: 
38478diff
changeset | 54 | import Markup_Tree._ | 
| 34557 | 55 | |
| 38563 | 56 | override def toString = | 
| 57 |     branches.toList.map(_._2) match {
 | |
| 58 | case Nil => "Empty" | |
| 59 |       case list => list.mkString("Tree(", ",", ")")
 | |
| 60 | } | |
| 61 | ||
| 45469 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 62 | private def overlapping(range: Text.Range): Branches.T = | 
| 45457 | 63 |   {
 | 
| 64 | val start = Text.Range(range.start) | |
| 65 | val stop = Text.Range(range.stop) | |
| 66 | val bs = branches.range(start, stop) | |
| 67 | // FIXME check after Scala 2.8.x | |
| 68 |     branches.get(stop) match {
 | |
| 45469 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 69 | case Some(end) if range overlaps end.range => bs + (end.range -> end) | 
| 45457 | 70 | case _ => bs | 
| 71 | } | |
| 72 | } | |
| 73 | ||
| 45469 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 74 | def + (new_markup: Text.Markup): Markup_Tree = | 
| 34703 | 75 |   {
 | 
| 45469 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 76 | val new_range = new_markup.range | 
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 77 | |
| 38578 | 78 |     branches.get(new_range) match {
 | 
| 45473 | 79 | case None => new Markup_Tree(branches, Entry(new_markup, empty)) | 
| 45469 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 80 | case Some(entry) => | 
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 81 | if (entry.range == new_range) | 
| 45473 | 82 | new Markup_Tree(branches, entry + new_markup.info) | 
| 45469 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 83 | else if (entry.range.contains(new_range)) | 
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 84 | new Markup_Tree(branches, entry.copy(subtree = entry.subtree + new_markup)) | 
| 38578 | 85 | else if (new_range.contains(branches.head._1) && new_range.contains(branches.last._1)) | 
| 45473 | 86 | new Markup_Tree(Branches.empty, Entry(new_markup, this)) | 
| 38482 
7b6ee937b75f
tuned Markup_Tree, using SortedMap more carefully;
 wenzelm parents: 
38479diff
changeset | 87 |         else {
 | 
| 45457 | 88 | val body = overlapping(new_range) | 
| 38578 | 89 |           if (body.forall(e => new_range.contains(e._1))) {
 | 
| 45469 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 90 | val rest = // branches -- body, modulo workarounds for Redblack in Scala 2.8.0 FIXME | 
| 38657 | 91 | if (body.size > 1) | 
| 92 | (Branches.empty /: branches)((rest, entry) => | |
| 93 | if (body.isDefinedAt(entry._1)) rest else rest + entry) | |
| 94 | else branches | |
| 45473 | 95 | new Markup_Tree(rest, Entry(new_markup, new Markup_Tree(body))) | 
| 38482 
7b6ee937b75f
tuned Markup_Tree, using SortedMap more carefully;
 wenzelm parents: 
38479diff
changeset | 96 | } | 
| 
7b6ee937b75f
tuned Markup_Tree, using SortedMap more carefully;
 wenzelm parents: 
38479diff
changeset | 97 |           else { // FIXME split markup!?
 | 
| 45469 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 98 |             System.err.println("Ignored overlapping markup information: " + new_markup)
 | 
| 38482 
7b6ee937b75f
tuned Markup_Tree, using SortedMap more carefully;
 wenzelm parents: 
38479diff
changeset | 99 | this | 
| 
7b6ee937b75f
tuned Markup_Tree, using SortedMap more carefully;
 wenzelm parents: 
38479diff
changeset | 100 | } | 
| 
7b6ee937b75f
tuned Markup_Tree, using SortedMap more carefully;
 wenzelm parents: 
38479diff
changeset | 101 | } | 
| 34703 | 102 | } | 
| 103 | } | |
| 104 | ||
| 46178 
1c5c88f6feb5
clarified Isabelle_Rendering vs. physical painting;
 wenzelm parents: 
46165diff
changeset | 105 | def cumulate[A](root_range: Text.Range, root_info: A, result_elements: Option[Set[String]], | 
| 
1c5c88f6feb5
clarified Isabelle_Rendering vs. physical painting;
 wenzelm parents: 
46165diff
changeset | 106 | result: PartialFunction[(A, Text.Markup), A]): Stream[Text.Info[A]] = | 
| 45459 | 107 |   {
 | 
| 46178 
1c5c88f6feb5
clarified Isabelle_Rendering vs. physical painting;
 wenzelm parents: 
46165diff
changeset | 108 | def results(x: A, entry: Entry): Option[A] = | 
| 
1c5c88f6feb5
clarified Isabelle_Rendering vs. physical painting;
 wenzelm parents: 
46165diff
changeset | 109 |       if (result_elements match { case Some(es) => es.exists(entry.elements) case None => true }) {
 | 
| 45474 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 110 | val (y, changed) = | 
| 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 111 | (entry.markup :\ (x, false))((info, res) => | 
| 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 112 |             {
 | 
| 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 113 | val (y, changed) = res | 
| 46165 | 114 | val arg = (y, Text.Info(entry.range, info)) | 
| 46178 
1c5c88f6feb5
clarified Isabelle_Rendering vs. physical painting;
 wenzelm parents: 
46165diff
changeset | 115 | if (result.isDefinedAt(arg)) (result(arg), true) | 
| 45474 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 116 | else res | 
| 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 117 | }) | 
| 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 118 | if (changed) Some(y) else None | 
| 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 119 | } | 
| 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 wenzelm parents: 
45473diff
changeset | 120 | else None | 
| 45467 | 121 | |
| 45459 | 122 | def stream( | 
| 123 | last: Text.Offset, | |
| 45469 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 124 | stack: List[(Text.Info[A], Stream[(Text.Range, Entry)])]): Stream[Text.Info[A]] = | 
| 45459 | 125 |     {
 | 
| 126 |       stack match {
 | |
| 45469 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 127 | case (parent, (range, entry) #:: more) :: rest => | 
| 45467 | 128 | val subrange = range.restrict(root_range) | 
| 45469 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 129 | val subtree = entry.subtree.overlapping(subrange).toStream | 
| 45459 | 130 | val start = subrange.start | 
| 131 | ||
| 46178 
1c5c88f6feb5
clarified Isabelle_Rendering vs. physical painting;
 wenzelm parents: 
46165diff
changeset | 132 |           results(parent.info, entry) match {
 | 
| 45469 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 133 | case Some(res) => | 
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 134 | val next = Text.Info(subrange, res) | 
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 135 | val nexts = stream(start, (next, subtree) :: (parent, more) :: rest) | 
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 136 | if (last < start) parent.restrict(Text.Range(last, start)) #:: nexts | 
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 137 | else nexts | 
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 138 | case None => stream(last, (parent, subtree #::: more) :: rest) | 
| 45459 | 139 | } | 
| 140 | ||
| 141 | case (parent, Stream.Empty) :: rest => | |
| 142 | val stop = parent.range.stop | |
| 143 | val nexts = stream(stop, rest) | |
| 144 | if (last < stop) parent.restrict(Text.Range(last, stop)) #:: nexts | |
| 145 | else nexts | |
| 146 | ||
| 147 | case Nil => | |
| 45467 | 148 | val stop = root_range.stop | 
| 149 | if (last < stop) Stream(Text.Info(Text.Range(last, stop), root_info)) | |
| 45459 | 150 | else Stream.empty | 
| 151 | } | |
| 152 | } | |
| 45467 | 153 | stream(root_range.start, | 
| 154 | List((Text.Info(root_range, root_info), overlapping(root_range).toStream))) | |
| 45459 | 155 | } | 
| 156 | ||
| 38577 | 157 | def swing_tree(parent: DefaultMutableTreeNode) | 
| 45455 | 158 | (swing_node: Text.Markup => DefaultMutableTreeNode) | 
| 38479 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 wenzelm parents: 
38478diff
changeset | 159 |   {
 | 
| 45469 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 160 |     for ((_, entry) <- branches) {
 | 
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 161 | var current = parent | 
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 162 |       for (info <- entry.markup) {
 | 
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 163 | val node = swing_node(Text.Info(entry.range, info)) | 
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 164 | current.add(node) | 
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 165 | current = node | 
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 166 | } | 
| 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 wenzelm parents: 
45468diff
changeset | 167 | entry.subtree.swing_tree(current)(swing_node) | 
| 34514 
2104a836b415
renamed fields of MarkupNode; implemented flatten and leafs
 immler@in.tum.de parents: 
34503diff
changeset | 168 | } | 
| 
2104a836b415
renamed fields of MarkupNode; implemented flatten and leafs
 immler@in.tum.de parents: 
34503diff
changeset | 169 | } | 
| 34717 
3f32e08bbb6c
sidekick root data: set buffer length to avoid crash of initial caret move;
 wenzelm parents: 
34708diff
changeset | 170 | } | 
| 34514 
2104a836b415
renamed fields of MarkupNode; implemented flatten and leafs
 immler@in.tum.de parents: 
34503diff
changeset | 171 |