src/Tools/jEdit/src/text_area_painter.scala
changeset 49356 6e0c0ffb6ec7
parent 49355 7d1af0a6e797
child 49357 34ac36642a31
equal deleted inserted replaced
49355:7d1af0a6e797 49356:6e0c0ffb6ec7
    73     pick_extension("org.gjt.sp.jedit.textarea.TextAreaPainter$PaintText")
    73     pick_extension("org.gjt.sp.jedit.textarea.TextAreaPainter$PaintText")
    74 
    74 
    75 
    75 
    76   /* common painter state */
    76   /* common painter state */
    77 
    77 
    78   @volatile private var painter_snapshot: Document.Snapshot = null
    78   @volatile private var painter_rendering: Isabelle_Rendering = null
    79   @volatile private var painter_clip: Shape = null
    79   @volatile private var painter_clip: Shape = null
    80 
    80 
    81   private val set_state = new TextAreaExtension
    81   private val set_state = new TextAreaExtension
    82   {
    82   {
    83     override def paintScreenLineRange(gfx: Graphics2D,
    83     override def paintScreenLineRange(gfx: Graphics2D,
    84       first_line: Int, last_line: Int, physical_lines: Array[Int],
    84       first_line: Int, last_line: Int, physical_lines: Array[Int],
    85       start: Array[Int], end: Array[Int], y: Int, line_height: Int)
    85       start: Array[Int], end: Array[Int], y: Int, line_height: Int)
    86     {
    86     {
    87       painter_snapshot = model.snapshot()
    87       painter_rendering = Isabelle_Rendering(model.snapshot(), Isabelle.options.value)
    88       painter_clip = gfx.getClip
    88       painter_clip = gfx.getClip
    89     }
    89     }
    90   }
    90   }
    91 
    91 
    92   private val reset_state = new TextAreaExtension
    92   private val reset_state = new TextAreaExtension
    93   {
    93   {
    94     override def paintScreenLineRange(gfx: Graphics2D,
    94     override def paintScreenLineRange(gfx: Graphics2D,
    95       first_line: Int, last_line: Int, physical_lines: Array[Int],
    95       first_line: Int, last_line: Int, physical_lines: Array[Int],
    96       start: Array[Int], end: Array[Int], y: Int, line_height: Int)
    96       start: Array[Int], end: Array[Int], y: Int, line_height: Int)
    97     {
    97     {
    98       painter_snapshot = null
    98       painter_rendering = null
    99       painter_clip = null
    99       painter_clip = null
   100     }
   100     }
   101   }
   101   }
   102 
   102 
   103   private def robust_snapshot(body: Document.Snapshot => Unit)
   103   private def robust_rendering(body: Isabelle_Rendering => Unit)
   104   {
   104   {
   105     doc_view.robust_body(()) { body(painter_snapshot) }
   105     doc_view.robust_body(()) { body(painter_rendering) }
   106   }
   106   }
   107 
   107 
   108 
   108 
   109   /* text background */
   109   /* text background */
   110 
   110 
   112   {
   112   {
   113     override def paintScreenLineRange(gfx: Graphics2D,
   113     override def paintScreenLineRange(gfx: Graphics2D,
   114       first_line: Int, last_line: Int, physical_lines: Array[Int],
   114       first_line: Int, last_line: Int, physical_lines: Array[Int],
   115       start: Array[Int], end: Array[Int], y: Int, line_height: Int)
   115       start: Array[Int], end: Array[Int], y: Int, line_height: Int)
   116     {
   116     {
   117       robust_snapshot { snapshot =>
   117       robust_rendering { rendering =>
   118         val ascent = text_area.getPainter.getFontMetrics.getAscent
   118         val ascent = text_area.getPainter.getFontMetrics.getAscent
   119 
   119 
   120         for (i <- 0 until physical_lines.length) {
   120         for (i <- 0 until physical_lines.length) {
   121           if (physical_lines(i) != -1) {
   121           if (physical_lines(i) != -1) {
   122             val line_range = doc_view.proper_line_range(start(i), end(i))
   122             val line_range = doc_view.proper_line_range(start(i), end(i))
   123 
   123 
   124             // background color (1)
   124             // background color (1)
   125             for {
   125             for {
   126               Text.Info(range, color) <- Isabelle_Rendering.background1(snapshot, line_range)
   126               Text.Info(range, color) <- rendering.background1(line_range)
   127               r <- gfx_range(range)
   127               r <- gfx_range(range)
   128             } {
   128             } {
   129               gfx.setColor(color)
   129               gfx.setColor(color)
   130               gfx.fillRect(r.x, y + i * line_height, r.length, line_height)
   130               gfx.fillRect(r.x, y + i * line_height, r.length, line_height)
   131             }
   131             }
   132 
   132 
   133             // background color (2)
   133             // background color (2)
   134             for {
   134             for {
   135               Text.Info(range, color) <- Isabelle_Rendering.background2(snapshot, line_range)
   135               Text.Info(range, color) <- rendering.background2(line_range)
   136               r <- gfx_range(range)
   136               r <- gfx_range(range)
   137             } {
   137             } {
   138               gfx.setColor(color)
   138               gfx.setColor(color)
   139               gfx.fillRect(r.x + 2, y + i * line_height + 2, r.length - 4, line_height - 4)
   139               gfx.fillRect(r.x + 2, y + i * line_height + 2, r.length - 4, line_height - 4)
   140             }
   140             }
   141 
   141 
   142             // squiggly underline
   142             // squiggly underline
   143             for {
   143             for {
   144               Text.Info(range, color) <- Isabelle_Rendering.squiggly_underline(snapshot, line_range)
   144               Text.Info(range, color) <- rendering.squiggly_underline(line_range)
   145               r <- gfx_range(range)
   145               r <- gfx_range(range)
   146             } {
   146             } {
   147               gfx.setColor(color)
   147               gfx.setColor(color)
   148               val x0 = (r.x / 2) * 2
   148               val x0 = (r.x / 2) * 2
   149               val y0 = r.y + ascent + 1
   149               val y0 = r.y + ascent + 1
   159   }
   159   }
   160 
   160 
   161 
   161 
   162   /* text */
   162   /* text */
   163 
   163 
   164   private def paint_chunk_list(snapshot: Document.Snapshot,
   164   private def paint_chunk_list(rendering: Isabelle_Rendering,
   165     gfx: Graphics2D, line_start: Text.Offset, head: Chunk, x: Float, y: Float): Float =
   165     gfx: Graphics2D, line_start: Text.Offset, head: Chunk, x: Float, y: Float): Float =
   166   {
   166   {
   167     val clip_rect = gfx.getClipBounds
   167     val clip_rect = gfx.getClipBounds
   168     val painter = text_area.getPainter
   168     val painter = text_area.getPainter
   169     val font_context = painter.getFontRenderContext
   169     val font_context = painter.getFontRenderContext
   188           if (text_area.isCaretVisible) doc_view.caret_range()
   188           if (text_area.isCaretVisible) doc_view.caret_range()
   189           else Text.Range(-1)
   189           else Text.Range(-1)
   190 
   190 
   191         val markup =
   191         val markup =
   192           for {
   192           for {
   193             r1 <- Isabelle_Rendering.text_color(snapshot, chunk_range, chunk_color)
   193             r1 <- rendering.text_color(chunk_range, chunk_color)
   194             r2 <- r1.try_restrict(chunk_range)
   194             r2 <- r1.try_restrict(chunk_range)
   195           } yield r2
   195           } yield r2
   196 
   196 
   197         val padded_markup =
   197         val padded_markup =
   198           if (markup.isEmpty)
   198           if (markup.isEmpty)
   244   {
   244   {
   245     override def paintScreenLineRange(gfx: Graphics2D,
   245     override def paintScreenLineRange(gfx: Graphics2D,
   246       first_line: Int, last_line: Int, physical_lines: Array[Int],
   246       first_line: Int, last_line: Int, physical_lines: Array[Int],
   247       start: Array[Int], end: Array[Int], y: Int, line_height: Int)
   247       start: Array[Int], end: Array[Int], y: Int, line_height: Int)
   248     {
   248     {
   249       robust_snapshot { snapshot =>
   249       robust_rendering { rendering =>
   250         val clip = gfx.getClip
   250         val clip = gfx.getClip
   251         val x0 = text_area.getHorizontalOffset
   251         val x0 = text_area.getHorizontalOffset
   252         val fm = text_area.getPainter.getFontMetrics
   252         val fm = text_area.getPainter.getFontMetrics
   253         var y0 = y + fm.getHeight - (fm.getLeading + 1) - fm.getDescent
   253         var y0 = y + fm.getHeight - (fm.getLeading + 1) - fm.getDescent
   254 
   254 
   258             val screen_line = first_line + i
   258             val screen_line = first_line + i
   259             val chunks = text_area.getChunksOfScreenLine(screen_line)
   259             val chunks = text_area.getChunksOfScreenLine(screen_line)
   260             if (chunks != null) {
   260             if (chunks != null) {
   261               val line_start = text_area.getBuffer.getLineStartOffset(line)
   261               val line_start = text_area.getBuffer.getLineStartOffset(line)
   262               gfx.clipRect(x0, y + line_height * i, Integer.MAX_VALUE, line_height)
   262               gfx.clipRect(x0, y + line_height * i, Integer.MAX_VALUE, line_height)
   263               val w = paint_chunk_list(snapshot, gfx, line_start, chunks, x0, y0).toInt
   263               val w = paint_chunk_list(rendering, gfx, line_start, chunks, x0, y0).toInt
   264               gfx.clipRect(x0 + w.toInt, 0, Integer.MAX_VALUE, Integer.MAX_VALUE)
   264               gfx.clipRect(x0 + w.toInt, 0, Integer.MAX_VALUE, Integer.MAX_VALUE)
   265               orig_text_painter.paintValidLine(gfx,
   265               orig_text_painter.paintValidLine(gfx,
   266                 screen_line, line, start(i), end(i), y + line_height * i)
   266                 screen_line, line, start(i), end(i), y + line_height * i)
   267               gfx.setClip(clip)
   267               gfx.setClip(clip)
   268             }
   268             }
   280   {
   280   {
   281     override def paintScreenLineRange(gfx: Graphics2D,
   281     override def paintScreenLineRange(gfx: Graphics2D,
   282       first_line: Int, last_line: Int, physical_lines: Array[Int],
   282       first_line: Int, last_line: Int, physical_lines: Array[Int],
   283       start: Array[Int], end: Array[Int], y: Int, line_height: Int)
   283       start: Array[Int], end: Array[Int], y: Int, line_height: Int)
   284     {
   284     {
   285       robust_snapshot { snapshot =>
   285       robust_rendering { rendering =>
   286         for (i <- 0 until physical_lines.length) {
   286         for (i <- 0 until physical_lines.length) {
   287           if (physical_lines(i) != -1) {
   287           if (physical_lines(i) != -1) {
   288             val line_range = doc_view.proper_line_range(start(i), end(i))
   288             val line_range = doc_view.proper_line_range(start(i), end(i))
   289 
   289 
   290             // foreground color
   290             // foreground color
   291             for {
   291             for {
   292               Text.Info(range, color) <- Isabelle_Rendering.foreground(snapshot, line_range)
   292               Text.Info(range, color) <- rendering.foreground(line_range)
   293               r <- gfx_range(range)
   293               r <- gfx_range(range)
   294             } {
   294             } {
   295               gfx.setColor(color)
   295               gfx.setColor(color)
   296               gfx.fillRect(r.x, y + i * line_height, r.length, line_height)
   296               gfx.fillRect(r.x, y + i * line_height, r.length, line_height)
   297             }
   297             }
   310             for {
   310             for {
   311               info <- doc_view.hyperlink_range()
   311               info <- doc_view.hyperlink_range()
   312               Text.Info(range, _) <- info.try_restrict(line_range)
   312               Text.Info(range, _) <- info.try_restrict(line_range)
   313               r <- gfx_range(range)
   313               r <- gfx_range(range)
   314             } {
   314             } {
   315               gfx.setColor(Isabelle_Rendering.color_value("hyperlink_color"))
   315               gfx.setColor(rendering.hyperlink_color)
   316               gfx.drawRect(r.x, y + i * line_height, r.length - 1, line_height - 1)
   316               gfx.drawRect(r.x, y + i * line_height, r.length - 1, line_height - 1)
   317             }
   317             }
   318           }
   318           }
   319         }
   319         }
   320       }
   320       }
   327   private class Caret_Painter(before: Boolean) extends TextAreaExtension
   327   private class Caret_Painter(before: Boolean) extends TextAreaExtension
   328   {
   328   {
   329     override def paintValidLine(gfx: Graphics2D,
   329     override def paintValidLine(gfx: Graphics2D,
   330       screen_line: Int, physical_line: Int, start: Int, end: Int, y: Int)
   330       screen_line: Int, physical_line: Int, start: Int, end: Int, y: Int)
   331     {
   331     {
   332       robust_snapshot { _ =>
   332       robust_rendering { _ =>
   333         if (before) gfx.clipRect(0, 0, 0, 0)
   333         if (before) gfx.clipRect(0, 0, 0, 0)
   334         else gfx.setClip(painter_clip)
   334         else gfx.setClip(painter_clip)
   335       }
   335       }
   336     }
   336     }
   337   }
   337   }
   344   private val caret_painter = new TextAreaExtension
   344   private val caret_painter = new TextAreaExtension
   345   {
   345   {
   346     override def paintValidLine(gfx: Graphics2D,
   346     override def paintValidLine(gfx: Graphics2D,
   347       screen_line: Int, physical_line: Int, start: Int, end: Int, y: Int)
   347       screen_line: Int, physical_line: Int, start: Int, end: Int, y: Int)
   348     {
   348     {
   349       robust_snapshot { _ =>
   349       robust_rendering { _ =>
   350         if (text_area.isCaretVisible) {
   350         if (text_area.isCaretVisible) {
   351           val caret = text_area.getCaretPosition
   351           val caret = text_area.getCaretPosition
   352           if (start <= caret && caret == end - 1) {
   352           if (start <= caret && caret == end - 1) {
   353             val painter = text_area.getPainter
   353             val painter = text_area.getPainter
   354             val fm = painter.getFontMetrics
   354             val fm = painter.getFontMetrics