def update(new_info: Option[Text.Info[A]]): Unit = { val old_text_info = the_text_info val new_text_info = for {
info <- new_info
s <- JEdit_Lib.get_text(text_area.getBuffer, info.range)
} yield (s, info)
if (new_text_info != old_text_info) {
caret_update() if (cursor >= 0) { if (new_text_info.isDefined) {
text_area.getPainter.setCursor(Cursor.getPredefinedCursor(cursor))
} else text_area.getPainter.resetCursor()
} for {
r0 <- JEdit_Lib.visible_range(text_area)
opt <- List(old_text_info, new_text_info)
(_, Text.Info(r1, _)) <- opt
r2 <- r1.try_restrict(r0) // FIXME more precise?!
} JEdit_Lib.invalidate_range(text_area, r2)
the_text_info = new_text_info
}
}
def update_rendering(rendering: JEdit_Rendering, range: Text.Range): Unit =
update(render(rendering)(range))
privateval focus_listener = new FocusAdapter { overridedef focusLost(e: FocusEvent): Unit = { robust_body(()) { active_reset() } }
}
privateval window_listener = new WindowAdapter { overridedef windowIconified(e: WindowEvent): Unit = { robust_body(()) { active_reset() } } overridedef windowDeactivated(e: WindowEvent): Unit = { robust_body(()) { active_reset() } }
}
privateval mouse_listener = new MouseAdapter { overridedef mousePressed(e: MouseEvent): Unit = {
robust_body(()) { if (!e.isConsumed() && e.getClickCount == 1) {
hyperlink_area.info match { case Some(Text.Info(range, link)) => if (!link.external) { try {
text_area.moveCaretPosition(range.start)
PIDE.plugin.navigator.record(Isabelle_Navigator.Pos(buffer, range.start))
} catch { case _: ArrayIndexOutOfBoundsException => case _: IllegalArgumentException =>
}
text_area.requestFocus()
}
link.follow(view)
e.consume() case None =>
}
active_area.text_info match { case Some((text, Text.Info(_, markup))) =>
Active.action(view, text, markup)
close_action()
e.consume() case None =>
}
}
}
}
}
privatedef mouse_inside_painter(): Boolean =
MouseInfo.getPointerInfo match { casenull => false case info => val point = info.getLocation val painter = text_area.getPainter
SwingUtilities.convertPointFromScreen(point, painter)
painter.contains(point)
}
privateval mouse_motion_listener = new MouseMotionAdapter { overridedef mouseDragged(evt: MouseEvent): Unit = {
robust_body(()) {
active_reset()
Completion_Popup.Text_Area.dismissed(text_area)
Pretty_Tooltip.dismiss_descendant(text_area.getPainter)
}
}
overridedef mouseMoved(evt: MouseEvent): Unit = {
robust_body(()) { val x = evt.getX val y = evt.getY val control = JEdit_Lib.command_modifier(evt)
if ((control || enable_hovering) && !buffer.isLoading) {
JEdit_Lib.buffer_lock(buffer) {
JEdit_Lib.pixel_range(text_area, x, y) match { case None => active_reset() case Some(range) => val rendering = get_rendering() for (area <- active_areas) { if (area.check_control(control) && !rendering.snapshot.is_outdated) {
area.update_rendering(rendering, range)
} else area.reset()
} if (JEdit_Lib.alt_modifier(evt)) {
highlight_area.info.map(_.range) match { case Some(range) =>
text_area.requestFocus()
text_area.selectNone()
text_area.addToSelection(new Selection.Range(range.start, range.stop)) case None =>
}
}
}
}
} else active_reset()
if (evt.getSource == text_area.getPainter) {
Pretty_Tooltip.invoke(() =>
robust_body(()) { if (mouse_inside_painter()) { val rendering = get_rendering() val snapshot = rendering.snapshot if (!snapshot.is_outdated) {
JEdit_Lib.pixel_range(text_area, x, y) match { case None => case Some(range) =>
rendering.tooltip(range, control) match { case None => case Some(tip) => val painter = text_area.getPainter val loc = new Point(x, y + painter.getLineHeight / 2) val results = snapshot.command_results(tip.range)
Pretty_Tooltip(view, painter, loc, rendering, results, tip.info)
}
}
}
}
})
}
}
}
}
/* text background */
privateval background_painter = new TextAreaExtension { overridedef paintScreenLineRange(
gfx: Graphics2D,
first_line: Int,
last_line: Int,
physical_lines: Array[Int],
start: Array[Int],
end: Array[Int],
y: Int,
line_height: Int
): Unit = {
robust_rendering { rendering => val fm = text_area.getPainter.getFontMetrics
for (i <- physical_lines.indices) { if (physical_lines(i) != -1) { val line_range = Text.Range(start(i), end(i) min buffer.getLength)
// line background color for (c <- rendering.line_background(line_range)) { val separator = rendering.line_separator(line_range) val sep = if (separator) (2 min (line_height / 2)) max (line_height / 8) else 0
gfx.setColor(rendering.color(c))
gfx.fillRect(0, y + i * line_height, text_area.getWidth, line_height - sep)
}
// background color for {
Text.Info(range, c) <-
rendering.background(Rendering.background_elements, line_range, caret_focus)
r <- painter_gfx_range(range)
} {
gfx.setColor(rendering.color(c))
gfx.fillRect(r.x, y + i * line_height, r.length, line_height)
}
// active area -- potentially from other snapshot for {
info <- active_area.info
Text.Info(range, _) <- info.try_restrict(line_range)
r <- painter_gfx_range(range)
} {
gfx.setColor(rendering.active_hover_color)
gfx.fillRect(r.x, y + i * line_height, r.length, line_height)
}
// squiggly underline for {
Text.Info(range, c) <- rendering.squiggly_underline(line_range)
r <- painter_gfx_range(range)
} {
gfx.setColor(rendering.color(c)) val x0 = (r.x / 2) * 2 val y0 = r.y + fm.getAscent + 1 for (x1 <- Range(x0, x0 + r.length, 2)) { val y1 = if (x1 % 4 < 2) y0 else y0 + 1
gfx.drawLine(x1, y1, x1 + 1, y1)
}
}
// spell checker for {
spell_checker <- PIDE.plugin.spell_checker.get
spell <- rendering.spell_checker(line_range)
text <- JEdit_Lib.get_text(buffer, spell.range)
info <- spell_checker.marked_words(spell.range.start, text)
r <- painter_gfx_range(info.range)
} {
gfx.setColor(rendering.spell_checker_color) val y0 = r.y + ((fm.getAscent + 4) min (line_height - 2))
gfx.drawLine(r.x, y0, r.x + r.length, y0)
}
}
}
}
}
}
val x = x0.toFloat val y = y0.toFloat
chunk_list.foldLeft(0.0f) { case (w, chunk) => val chunk_offset = line_start + chunk.offset if (x + w + chunk.width > clip_rect.x &&
x + w < clip_rect.x + clip_rect.width && chunk.length > 0) { val chunk_range = Text.Range(chunk_offset, chunk_offset + chunk.length) val chunk_font = chunk.style.getFont val chunk_color = chunk.style.getForegroundColor val chunk_text = new AttributedString(chunk.str)
// font
chunk_text.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_LTR)
chunk_text.addAttribute(TextAttribute.FONT, chunk_font) if (chunk.font_subst) { for {
(c, i) <- Codepoint.iterator_offset(chunk.str) if !chunk_font.canDisplay(c)
subst_font <- font_subst.get(c)
} { val r = Text.Range(i, i + Character.charCount(c)) + chunk_offset val font = JEditChunk.deriveSubstFont(chunk_font, subst_font)
chunk_attrib(TextAttribute.FONT, font, r)
}
}
// color
chunk_text.addAttribute(TextAttribute.FOREGROUND, chunk_color) for {
Text.Info(r1, color) <- rendering.text_color(chunk_range, chunk_color).iterator
r2 <- r1.try_restrict(chunk_range) if !r2.is_singularity
} chunk_attrib(TextAttribute.FOREGROUND, color, r2)
// caret for { r <- caret_range.try_restrict(chunk_range) if !r.is_singularity } {
chunk_attrib(TextAttribute.FOREGROUND, caret_color(rendering, r.start), r)
chunk_attrib(TextAttribute.SWAP_COLORS, TextAttribute.SWAP_COLORS_ON, r)
}
gfx.drawString(chunk_text.getIterator, x + w, y)
}
w + chunk.width
}
}
privateval text_painter = new TextAreaExtension { overridedef paintScreenLineRange(
gfx: Graphics2D,
first_line: Int,
last_line: Int,
physical_lines: Array[Int],
start: Array[Int],
end: Array[Int],
y: Int,
line_height: Int
): Unit = {
robust_rendering { rendering => val painter = text_area.getPainter val fm = painter.getFontMetrics val lm = painter.getFont.getLineMetrics(" ", painter.getFontRenderContext)
val clip = gfx.getClip val x0 = text_area.getHorizontalOffset var y0 = y + painter.getLineHeight - (fm.getLeading + 1) - fm.getDescent
val (bullet_x, bullet_y, bullet_w, bullet_h) = { val w = fm.charWidth(' ') val b = (w / 2) max 1 val c = (lm.getAscent + lm.getStrikethroughOffset).round
((w - b + 1) / 2, c - b / 2, w - b, line_height - b)
}
val font_subst = new Font_Subst
for (i <- physical_lines.indices) { val line = physical_lines(i) if (line != -1) { val line_range = Text.Range(start(i), end(i) min buffer.getLength)
// text chunks val screen_line = first_line + i val chunk_list = make_chunk_list(text_area.getChunksOfScreenLine(screen_line)) if (chunk_list.nonEmpty) { try { val line_start = buffer.getLineStartOffset(line) val caret_range = if (caret_enabled) JEdit_Lib.caret_range(text_area) else Text.Range.offside
gfx.clipRect(x0, y + line_height * i, Int.MaxValue, line_height) val w =
paint_chunk_list(rendering, font_subst, gfx,
line_start, caret_range, chunk_list, x0, y0)
gfx.clipRect(x0 + w.toInt, 0, Int.MaxValue, Int.MaxValue)
orig_text_painter.paintValidLine(gfx,
screen_line, line, start(i), end(i), y + line_height * i)
} finally { gfx.setClip(clip) }
}
// bullet bar for {
Text.Info(range, color) <- rendering.bullet(line_range)
r <- painter_gfx_range(range)
} {
gfx.setColor(color)
gfx.fillRect(r.x + bullet_x, y + i * line_height + bullet_y,
r.length - bullet_w, line_height - bullet_h)
}
}
y0 += line_height
}
}
}
}
/* foreground */
privateval foreground_painter = new TextAreaExtension { overridedef paintScreenLineRange(
gfx: Graphics2D,
first_line: Int,
last_line: Int,
physical_lines: Array[Int],
start: Array[Int],
end: Array[Int],
y: Int,
line_height: Int
): Unit = {
robust_rendering { rendering => val search_pattern = get_search_pattern() for (i <- physical_lines.indices) { if (physical_lines(i) != -1) { val line_range = Text.Range(start(i), end(i) min buffer.getLength)
// foreground color for {
Text.Info(range, c) <- rendering.foreground(line_range)
r <- painter_gfx_range(range)
} {
gfx.setColor(rendering.color(c))
gfx.fillRect(r.x, y + i * line_height, r.length, line_height)
}
// search pattern for {
regex <- search_pattern
range <- JEdit_Lib.search_text(buffer, line_range, regex)
r <- painter_gfx_range(range)
} {
gfx.setColor(rendering.search_color)
gfx.fillRect(r.x, y + i * line_height, r.length, line_height)
}
// highlight range -- potentially from other snapshot for {
info <- highlight_area.info
Text.Info(range, color) <- info.try_restrict(line_range)
r <- painter_gfx_range(range)
} {
gfx.setColor(color)
gfx.fillRect(r.x, y + i * line_height, r.length, line_height)
}
// hyperlink range -- potentially from other snapshot for {
info <- hyperlink_area.info
Text.Info(range, _) <- info.try_restrict(line_range)
r <- painter_gfx_range(range)
} {
gfx.setColor(rendering.hyperlink_color)
gfx.drawRect(r.x, y + i * line_height, r.length - 1, line_height - 1)
}
// entity def range if (!active_exists() && caret_visible) { for {
Text.Info(range, color) <- rendering.entity_ref(line_range, caret_focus)
r <- painter_gfx_range(range)
} {
gfx.setColor(color)
gfx.drawRect(r.x, y + i * line_height, r.length - 1, line_height - 1)
}
}
// completion range if (!active_exists() && caret_visible) { for {
completion <- Completion_Popup.Text_Area(text_area)
Text.Info(range, color) <- completion.rendering(rendering, line_range)
r <- painter_gfx_range(range)
} {
gfx.setColor(color)
gfx.drawRect(r.x, y + i * line_height, r.length - 1, line_height - 1)
}
}
}
}
}
}
}
privateval before_caret_painter1 = new Caret_Painter(true) privateval after_caret_painter1 = new Caret_Painter(false) privateval before_caret_painter2 = new Caret_Painter(true) privateval after_caret_painter2 = new Caret_Painter(false)
privateval caret_painter = new TextAreaExtension { overridedef paintValidLine(
gfx: Graphics2D,
screen_line: Int,
physical_line: Int,
start: Int,
end: Int,
y: Int
): Unit = {
robust_rendering { rendering => if (caret_visible) { val caret = text_area.getCaretPosition if (caret_enabled && start <= caret && caret == end - 1) { val painter = text_area.getPainter val fm = painter.getFontMetrics
val offset = caret - text_area.getLineStartOffset(physical_line) val x = text_area.offsetToXY(physical_line, offset).x val y1 = y + painter.getLineHeight - (fm.getLeading + 1) - fm.getDescent
val astr = new AttributedString(" ")
astr.addAttribute(TextAttribute.FONT, painter.getFont)
astr.addAttribute(TextAttribute.FOREGROUND, caret_color(rendering, caret))
astr.addAttribute(TextAttribute.SWAP_COLORS, TextAttribute.SWAP_COLORS_ON)
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.