15 import org.gjt.sp.jedit.Debug |
15 import org.gjt.sp.jedit.Debug |
16 import org.gjt.sp.jedit.syntax.{DisplayTokenHandler, Chunk} |
16 import org.gjt.sp.jedit.syntax.{DisplayTokenHandler, Chunk} |
17 import org.gjt.sp.jedit.textarea.{JEditTextArea, TextAreaExtension, TextAreaPainter} |
17 import org.gjt.sp.jedit.textarea.{JEditTextArea, TextAreaExtension, TextAreaPainter} |
18 |
18 |
19 |
19 |
20 class Text_Painter(model: Document_Model, text_area: JEditTextArea) extends TextAreaExtension |
20 class Text_Painter(doc_view: Document_View) extends TextAreaExtension |
21 { |
21 { |
|
22 private val text_area = doc_view.text_area |
|
23 |
22 private val orig_text_painter: TextAreaExtension = |
24 private val orig_text_painter: TextAreaExtension = |
23 { |
25 { |
24 val name = "org.gjt.sp.jedit.textarea.TextAreaPainter$PaintText" |
26 val name = "org.gjt.sp.jedit.textarea.TextAreaPainter$PaintText" |
25 text_area.getPainter.getExtensions.iterator.filter(x => x.getClass.getName == name).toList |
27 text_area.getPainter.getExtensions.iterator.filter(x => x.getClass.getName == name).toList |
26 match { |
28 match { |
31 |
33 |
32 override def paintScreenLineRange(gfx: Graphics2D, |
34 override def paintScreenLineRange(gfx: Graphics2D, |
33 first_line: Int, last_line: Int, physical_lines: Array[Int], |
35 first_line: Int, last_line: Int, physical_lines: Array[Int], |
34 start: Array[Int], end: Array[Int], y_start: Int, line_height: Int) |
36 start: Array[Int], end: Array[Int], y_start: Int, line_height: Int) |
35 { |
37 { |
36 def paint_chunk_list(head: Chunk, x: Float, y: Float): Float = |
|
37 { |
|
38 val clip_rect = gfx.getClipBounds |
|
39 var w = 0.0f |
|
40 var chunk = head |
|
41 while (chunk != null) { |
|
42 if (x + w + chunk.width > clip_rect.x && |
|
43 x + w < clip_rect.x + clip_rect.width && |
|
44 chunk.accessable && chunk.visible) |
|
45 { |
|
46 gfx.setFont(chunk.style.getFont) |
|
47 gfx.setColor(chunk.style.getForegroundColor) |
|
48 if (!Debug.DISABLE_GLYPH_VECTOR && chunk.gv != null) |
|
49 gfx.drawGlyphVector(chunk.gv, x + w, y) |
|
50 else if (chunk.str != null) |
|
51 gfx.drawString(chunk.str, (x + w).toInt, y.toInt) |
|
52 } |
|
53 w += chunk.width |
|
54 chunk = chunk.next.asInstanceOf[Chunk] |
|
55 } |
|
56 w |
|
57 } |
|
58 |
|
59 val buffer = text_area.getBuffer |
38 val buffer = text_area.getBuffer |
60 Isabelle.swing_buffer_lock(buffer) { |
39 Isabelle.swing_buffer_lock(buffer) { |
61 val painter = text_area.getPainter |
40 val painter = text_area.getPainter |
62 val font = painter.getFont |
41 val font = painter.getFont |
63 val font_context = painter.getFontRenderContext |
42 val font_context = painter.getFontRenderContext |
64 val fm = painter.getFontMetrics |
43 val font_metrics = painter.getFontMetrics |
|
44 |
|
45 def paint_chunk_list(head_offset: Text.Offset, head: Chunk, x: Float, y: Float): Float = |
|
46 { |
|
47 val clip_rect = gfx.getClipBounds |
|
48 |
|
49 var w = 0.0f |
|
50 var offset = head_offset |
|
51 var chunk = head |
|
52 while (chunk != null) { |
|
53 val chunk_length = if (chunk.str == null) 0 else chunk.str.length |
|
54 |
|
55 if (x + w + chunk.width > clip_rect.x && |
|
56 x + w < clip_rect.x + clip_rect.width && |
|
57 chunk.accessable && chunk.visible) |
|
58 { |
|
59 val chunk_range = Text.Range(offset, offset + chunk_length) |
|
60 val chunk_font = chunk.style.getFont |
|
61 val chunk_color = chunk.style.getForegroundColor |
|
62 |
|
63 val markup = |
|
64 doc_view.text_area_snapshot.select_markup(chunk_range)(Isabelle_Markup.foreground) |
|
65 |
|
66 gfx.setFont(chunk_font) |
|
67 if (!Debug.DISABLE_GLYPH_VECTOR && chunk.gv != null && |
|
68 markup.forall(info => info.info.isEmpty)) { |
|
69 gfx.setColor(chunk_color) |
|
70 gfx.drawGlyphVector(chunk.gv, x + w, y) |
|
71 } |
|
72 else { |
|
73 var xpos = x + w |
|
74 for (Text.Info(range, info) <- markup) { |
|
75 val str = chunk.str.substring(range.start - offset, range.stop - offset) |
|
76 gfx.setColor(info.getOrElse(chunk_color)) |
|
77 gfx.drawString(str, xpos.toInt, y.toInt) |
|
78 xpos += chunk_font.getStringBounds(str, font_context).getWidth.toFloat |
|
79 } |
|
80 } |
|
81 } |
|
82 w += chunk.width |
|
83 offset += chunk_length |
|
84 chunk = chunk.next.asInstanceOf[Chunk] |
|
85 } |
|
86 w |
|
87 } |
65 |
88 |
66 // see org.gjt.sp.jedit.textarea.TextArea.propertiesChanged |
89 // see org.gjt.sp.jedit.textarea.TextArea.propertiesChanged |
67 // see org.gjt.sp.jedit.textarea.TextArea.setMaxLineLength |
90 // see org.gjt.sp.jedit.textarea.TextArea.setMaxLineLength |
68 val char_width = font.getStringBounds(" ", font_context).getWidth.round.toInt |
91 val char_width = font.getStringBounds(" ", font_context).getWidth.round.toInt |
69 val soft_wrap = buffer.getStringProperty("wrap") == "soft" |
92 val soft_wrap = buffer.getStringProperty("wrap") == "soft" |
96 result |
119 result |
97 } |
120 } |
98 |
121 |
99 val clip = gfx.getClip |
122 val clip = gfx.getClip |
100 val x0 = text_area.getHorizontalOffset |
123 val x0 = text_area.getHorizontalOffset |
101 var y0 = y_start + fm.getHeight - (fm.getLeading + 1) - fm.getDescent |
124 var y0 = |
|
125 y_start + font_metrics.getHeight - (font_metrics.getLeading + 1) - font_metrics.getDescent |
|
126 |
102 for (i <- 0 until physical_lines.length) { |
127 for (i <- 0 until physical_lines.length) { |
103 if (physical_lines(i) != -1) { |
128 if (physical_lines(i) != -1) { |
104 line_infos.get(start(i)) match { |
129 line_infos.get(start(i)) match { |
105 case Some(chunk) => |
130 case Some(chunk) => |
106 val w = paint_chunk_list(chunk, x0, y0).toInt |
131 val w = paint_chunk_list(start(i), chunk, x0, y0).toInt |
107 gfx.clipRect(x0 + w, 0, Integer.MAX_VALUE, Integer.MAX_VALUE) |
132 gfx.clipRect(x0 + w, 0, Integer.MAX_VALUE, Integer.MAX_VALUE) |
108 orig_text_painter.paintValidLine(gfx, |
133 orig_text_painter.paintValidLine(gfx, |
109 first_line + i, physical_lines(i), start(i), end(i), y_start + line_height * i) |
134 first_line + i, physical_lines(i), start(i), end(i), y_start + line_height * i) |
110 gfx.setClip(clip) |
135 gfx.setClip(clip) |
111 |
136 |