# HG changeset patch # User wenzelm # Date 1347544902 -7200 # Node ID 977cf0788b30d4859af61f7a14dcae69bafde547 # Parent f182f7fa158f3ac365adf5527ffc1b3d66463d1c more efficient painting based on cached result; diff -r f182f7fa158f -r 977cf0788b30 src/Pure/PIDE/document.scala --- a/src/Pure/PIDE/document.scala Thu Sep 13 11:13:00 2012 +0200 +++ b/src/Pure/PIDE/document.scala Thu Sep 13 16:01:42 2012 +0200 @@ -290,6 +290,7 @@ def convert(range: Text.Range): Text.Range def revert(i: Text.Offset): Text.Offset def revert(range: Text.Range): Text.Range + def eq_markup(other: Snapshot): Boolean def cumulate_markup[A](range: Text.Range, info: A, elements: Option[Set[String]], result: PartialFunction[(A, Text.Markup), A]): Stream[Text.Info[A]] def select_markup[A](range: Text.Range, elements: Option[Set[String]], @@ -479,7 +480,8 @@ // persistent user-view - def snapshot(name: Node.Name, pending_edits: List[Text.Edit]): Snapshot = + def snapshot(name: Node.Name = Node.Name.empty, pending_edits: List[Text.Edit] = Nil) + : Snapshot = { val stable = recent_stable val latest = history.tip @@ -503,6 +505,16 @@ def convert(range: Text.Range) = (range /: edits)((r, edit) => edit.convert(r)) def revert(range: Text.Range) = (range /: reverse_edits)((r, edit) => edit.revert(r)) + def eq_markup(other: Snapshot): Boolean = + !is_outdated && !other.is_outdated && + node.commands.size == other.node.commands.size && + ((node.commands.iterator zip other.node.commands.iterator) forall { + case (cmd1, cmd2) => + cmd1.source == cmd2.source && + (state.command_state(version, cmd1).markup eq + other.state.command_state(other.version, cmd2).markup) + }) + def cumulate_markup[A](range: Text.Range, info: A, elements: Option[Set[String]], result: PartialFunction[(A, Text.Markup), A]): Stream[Text.Info[A]] = { diff -r f182f7fa158f -r 977cf0788b30 src/Tools/jEdit/src/text_overview.scala --- a/src/Tools/jEdit/src/text_overview.scala Thu Sep 13 11:13:00 2012 +0200 +++ b/src/Tools/jEdit/src/text_overview.scala Thu Sep 13 16:01:42 2012 +0200 @@ -11,7 +11,7 @@ import scala.annotation.tailrec -import java.awt.{Graphics, Graphics2D, BorderLayout, Dimension} +import java.awt.{Graphics, Graphics2D, BorderLayout, Dimension, Color} import java.awt.event.{MouseAdapter, MouseEvent} import javax.swing.{JPanel, ToolTipManager} @@ -48,6 +48,17 @@ super.removeNotify } + + /* painting based on cached result */ + + private var cached_colors: List[(Color, Int, Int)] = Nil + + private var last_snapshot = Document.State.init.snapshot() + private var last_line_count = 0 + private var last_char_count = 0 + private var last_L = 0 + private var last_H = 0 + override def paintComponent(gfx: Graphics) { super.paintComponent(gfx) @@ -57,39 +68,64 @@ Isabelle.buffer_lock(buffer) { val snapshot = doc_view.model.snapshot() - gfx.setColor(getBackground) - gfx.asInstanceOf[Graphics2D].fill(gfx.getClipBounds) + if (snapshot.is_outdated) { + gfx.setColor(Isabelle_Rendering.color_value("color_outdated")) + gfx.asInstanceOf[Graphics2D].fill(gfx.getClipBounds) + } + else { + gfx.setColor(getBackground) + gfx.asInstanceOf[Graphics2D].fill(gfx.getClipBounds) + + val line_count = buffer.getLineCount + val char_count = buffer.getLength - val line_count = buffer.getLineCount - val char_count = buffer.getLength + val L = lines() + val H = getHeight() - val L = lines() - val H = getHeight() + if (!(line_count == last_line_count && char_count == last_char_count && + L == last_L && H == last_H && (snapshot eq_markup last_snapshot))) + { + @tailrec def loop(l: Int, h: Int, p: Int, q: Int, colors: List[(Color, Int, Int)]) + : List[(Color, Int, Int)] = + { + if (l < line_count && h < H) { + val p1 = p + H + val q1 = q + HEIGHT * L + val (l1, h1) = + if (p1 >= q1) (l + 1, h + (p1 - q) / L) + else (l + (q1 - p) / H, h + HEIGHT) - @tailrec def paint_loop(l: Int, h: Int, p: Int, q: Int): Unit = - { - if (l < line_count && h < H) { - val p1 = p + H - val q1 = q + HEIGHT * L - val (l1, h1) = - if (p1 >= q1) (l + 1, h + (p1 - q) / L) - else (l + (q1 - p) / H, h + HEIGHT) + val start = buffer.getLineStartOffset(l) + val end = + if (l1 < line_count) buffer.getLineStartOffset(l1) + else char_count + val range = Text.Range(start, end) - val start = buffer.getLineStartOffset(l) - val end = - if (l1 < line_count) buffer.getLineStartOffset(l1) - else char_count + val colors1 = + (Isabelle_Rendering.overview_color(snapshot, range), colors) match { + case (Some(color), (old_color, old_h, old_h1) :: rest) + if color == old_color && old_h1 == h => (color, old_h, h1) :: rest + case (Some(color), _) => (color, h, h1) :: colors + case (None, _) => colors + } + loop(l1, h1, p + (l1 - l) * H, q + (h1 - h) * L, colors1) + } + else colors.reverse + } + cached_colors = loop(0, 0, 0, 0, Nil) - Isabelle_Rendering.overview_color(snapshot, Text.Range(start, end)) match { - case None => - case Some(color) => - gfx.setColor(color) - gfx.fillRect(0, h, getWidth, h1 - h) - } - paint_loop(l1, h1, p + (l1 - l) * H, q + (h1 - h) * L) + last_snapshot = snapshot + last_line_count = line_count + last_char_count = char_count + last_L = L + last_H = H + } + + for ((color, h, h1) <- cached_colors) { + gfx.setColor(color) + gfx.fillRect(0, h, getWidth, h1 - h) } } - paint_loop(0, 0, 0, 0) } } }