src/Tools/jEdit/src/text_painter.scala
author wenzelm
Mon, 13 Jun 2011 13:53:41 +0200
changeset 43374 df1be524e60c
parent 43373 639c3aca2ed3
child 43375 09d992ab57c6
permissions -rw-r--r--
tuned;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
43369
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
     1
/*  Title:      Tools/jEdit/src/text_painter.scala
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
     3
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
     4
Replacement painter for jEdit text area.
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
     5
*/
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
     6
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
     7
package isabelle.jedit
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
     8
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
     9
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    10
import isabelle._
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    11
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    12
import java.awt.{Graphics, Graphics2D}
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    13
import java.util.ArrayList
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    14
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    15
import org.gjt.sp.jedit.Debug
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    16
import org.gjt.sp.jedit.syntax.{DisplayTokenHandler, Chunk}
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    17
import org.gjt.sp.jedit.textarea.{JEditTextArea, TextAreaExtension, TextAreaPainter}
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    18
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    19
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    20
class Text_Painter(model: Document_Model, text_area: JEditTextArea) extends TextAreaExtension
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    21
{
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    22
  private val orig_text_painter: TextAreaExtension =
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    23
  {
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    24
    val name = "org.gjt.sp.jedit.textarea.TextAreaPainter$PaintText"
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    25
    text_area.getPainter.getExtensions.iterator.filter(x => x.getClass.getName == name).toList
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    26
    match {
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    27
      case List(x) => x
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    28
      case _ => error("Expected exactly one " + name)
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    29
    }
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    30
  }
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    31
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    32
  override def paintScreenLineRange(gfx: Graphics2D,
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    33
    first_line: Int, last_line: Int, physical_lines: Array[Int],
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    34
    start: Array[Int], end: Array[Int], y: Int, line_height: Int)
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    35
  {
43373
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    36
    val buffer = text_area.getBuffer
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    37
    Isabelle.swing_buffer_lock(buffer) {
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    38
      val painter = text_area.getPainter
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    39
      val font = painter.getFont
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    40
      val font_context = painter.getFontRenderContext
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    41
      val fm = painter.getFontMetrics
43369
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    42
43373
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    43
      // see org.gjt.sp.jedit.textarea.TextArea.propertiesChanged
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    44
      // see org.gjt.sp.jedit.textarea.TextArea.setMaxLineLength
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    45
      val char_width = font.getStringBounds(" ", font_context).getWidth.round.toInt
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    46
      val soft_wrap = buffer.getStringProperty("wrap") == "soft"
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    47
      val wrap_margin =
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    48
      {
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    49
        val max = buffer.getIntegerProperty("maxLineLen", 0)
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    50
        if (max > 0) font.getStringBounds(" " * max, font_context).getWidth.toInt
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    51
        else if (soft_wrap) painter.getWidth - char_width * 3
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    52
        else 0
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    53
      }.toFloat
43371
98de43fc9733 more precise imitation of original TextAreaPainter$PaintText;
wenzelm
parents: 43370
diff changeset
    54
43373
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    55
      val line_infos: Map[Text.Offset, Chunk] =
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    56
      {
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    57
        val out = new ArrayList[Chunk]
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    58
        val handler = new DisplayTokenHandler
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    59
        val margin = if (soft_wrap) wrap_margin else 0.0f
43371
98de43fc9733 more precise imitation of original TextAreaPainter$PaintText;
wenzelm
parents: 43370
diff changeset
    60
43373
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    61
        var result = Map[Text.Offset, Chunk]()
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    62
        for (line <- physical_lines.iterator.filter(i => i != -1)) {
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    63
          out.clear
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    64
          handler.init(painter.getStyles, font_context, painter, out, margin)
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    65
          buffer.markTokens(line, handler)
43371
98de43fc9733 more precise imitation of original TextAreaPainter$PaintText;
wenzelm
parents: 43370
diff changeset
    66
43373
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    67
          val line_start = buffer.getLineStartOffset(line)
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    68
          for (i <- 0 until out.size) {
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    69
            val chunk = out.get(i)
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    70
            result += (line_start + chunk.offset -> chunk)
43371
98de43fc9733 more precise imitation of original TextAreaPainter$PaintText;
wenzelm
parents: 43370
diff changeset
    71
          }
98de43fc9733 more precise imitation of original TextAreaPainter$PaintText;
wenzelm
parents: 43370
diff changeset
    72
        }
43373
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    73
        result
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    74
      }
43369
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    75
43373
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    76
      val clip = gfx.getClip
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    77
      val x0 = text_area.getHorizontalOffset
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    78
      var y0 = y + fm.getHeight - (fm.getLeading + 1) - fm.getDescent
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    79
      for (i <- 0 until physical_lines.length) {
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    80
        if (physical_lines(i) != -1) {
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    81
          line_infos.get(start(i)) match {
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    82
            case Some(chunk) =>
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    83
              val w = Chunk.paintChunkList(chunk, gfx, x0, y0, !Debug.DISABLE_GLYPH_VECTOR).toInt
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    84
              gfx.clipRect(x0 + w, 0, Integer.MAX_VALUE, Integer.MAX_VALUE)
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    85
              orig_text_painter.paintValidLine(
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    86
                gfx, first_line + i, physical_lines(i), start(i), end(i), y + line_height * i)
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    87
              gfx.setClip(clip)
43372
2df2144b0910 use orig_text_painter for extras outside main text (also required to update internal line infos);
wenzelm
parents: 43371
diff changeset
    88
43373
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    89
            case None =>
43369
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    90
          }
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    91
        }
43373
639c3aca2ed3 always use our text painter;
wenzelm
parents: 43372
diff changeset
    92
        y0 += line_height
43369
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    93
      }
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    94
    }
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    95
  }
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    96
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    97
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    98
  /* activation */
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
    99
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
   100
  def activate()
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
   101
  {
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
   102
    val painter = text_area.getPainter
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
   103
    painter.removeExtension(orig_text_painter)
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
   104
    painter.addExtension(TextAreaPainter.TEXT_LAYER, this)
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
   105
  }
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
   106
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
   107
  def deactivate()
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
   108
  {
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
   109
    val painter = text_area.getPainter
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
   110
    painter.removeExtension(this)
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
   111
    painter.addExtension(TextAreaPainter.TEXT_LAYER, orig_text_painter)
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
   112
  }
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
   113
}
4c86b3405010 separate isabelle.jedit.Text_Painter, which actually replaces the original TextAreaPainter$PaintText instance;
wenzelm
parents:
diff changeset
   114