src/Tools/jEdit/src/rich_text_area.scala
changeset 75393 87ebf5a50283
parent 73884 0a12ca4f3e8d
child 75394 42267c650205
equal deleted inserted replaced
75388:b3ca4a6ed74b 75393:87ebf5a50283
    31   get_rendering: () => JEdit_Rendering,
    31   get_rendering: () => JEdit_Rendering,
    32   close_action: () => Unit,
    32   close_action: () => Unit,
    33   get_search_pattern: () => Option[Regex],
    33   get_search_pattern: () => Option[Regex],
    34   caret_update: () => Unit,
    34   caret_update: () => Unit,
    35   caret_visible: Boolean,
    35   caret_visible: Boolean,
    36   enable_hovering: Boolean)
    36   enable_hovering: Boolean
    37 {
    37 ) {
    38   private val buffer = text_area.getBuffer
    38   private val buffer = text_area.getBuffer
    39 
    39 
    40 
    40 
    41   /* robust extension body */
    41   /* robust extension body */
    42 
    42 
    43   def check_robust_body: Boolean =
    43   def check_robust_body: Boolean =
    44     GUI_Thread.require { buffer == text_area.getBuffer }
    44     GUI_Thread.require { buffer == text_area.getBuffer }
    45 
    45 
    46   def robust_body[A](default: A)(body: => A): A =
    46   def robust_body[A](default: A)(body: => A): A = {
    47   {
       
    48     try {
    47     try {
    49       if (check_robust_body) body
    48       if (check_robust_body) body
    50       else {
    49       else {
    51         Log.log(Log.ERROR, this, ERROR("Implicit change of text area buffer"))
    50         Log.log(Log.ERROR, this, ERROR("Implicit change of text area buffer"))
    52         default
    51         default
    56   }
    55   }
    57 
    56 
    58 
    57 
    59   /* original painters */
    58   /* original painters */
    60 
    59 
    61   private def pick_extension(name: String): TextAreaExtension =
    60   private def pick_extension(name: String): TextAreaExtension = {
    62   {
       
    63     text_area.getPainter.getExtensions.iterator.filter(x => x.getClass.getName == name).toList
    61     text_area.getPainter.getExtensions.iterator.filter(x => x.getClass.getName == name).toList
    64     match {
    62     match {
    65       case List(x) => x
    63       case List(x) => x
    66       case _ => error("Expected exactly one " + name)
    64       case _ => error("Expected exactly one " + name)
    67     }
    65     }
    79     if (caret_focus_modifier) Text.Range.full
    77     if (caret_focus_modifier) Text.Range.full
    80     else JEdit_Lib.visible_range(text_area) getOrElse Text.Range.offside
    78     else JEdit_Lib.visible_range(text_area) getOrElse Text.Range.offside
    81 
    79 
    82   private val key_listener =
    80   private val key_listener =
    83     JEdit_Lib.key_listener(
    81     JEdit_Lib.key_listener(
    84       key_pressed = (evt: KeyEvent) =>
    82       key_pressed = (evt: KeyEvent) => {
    85       {
       
    86         val mod = PIDE.options.string("jedit_focus_modifier")
    83         val mod = PIDE.options.string("jedit_focus_modifier")
    87         val old = caret_focus_modifier
    84         val old = caret_focus_modifier
    88         caret_focus_modifier = (mod.nonEmpty && mod == JEdit_Lib.modifier_string(evt))
    85         caret_focus_modifier = (mod.nonEmpty && mod == JEdit_Lib.modifier_string(evt))
    89         if (caret_focus_modifier != old) caret_update()
    86         if (caret_focus_modifier != old) caret_update()
    90       },
    87       },
    91       key_released = _ =>
    88       key_released = _ => {
    92       {
       
    93         if (caret_focus_modifier) {
    89         if (caret_focus_modifier) {
    94           caret_focus_modifier = false
    90           caret_focus_modifier = false
    95           caret_update()
    91           caret_update()
    96         }
    92         }
    97       })
    93       })
   101 
    97 
   102   @volatile private var painter_rendering: JEdit_Rendering = null
    98   @volatile private var painter_rendering: JEdit_Rendering = null
   103   @volatile private var painter_clip: Shape = null
    99   @volatile private var painter_clip: Shape = null
   104   @volatile private var caret_focus = Rendering.Focus.empty
   100   @volatile private var caret_focus = Rendering.Focus.empty
   105 
   101 
   106   private val set_state = new TextAreaExtension
   102   private val set_state = new TextAreaExtension {
   107   {
   103     override def paintScreenLineRange(
   108     override def paintScreenLineRange(gfx: Graphics2D,
   104       gfx: Graphics2D,
   109       first_line: Int, last_line: Int, physical_lines: Array[Int],
   105       first_line: Int,
   110       start: Array[Int], end: Array[Int], y: Int, line_height: Int): Unit =
   106       last_line: Int,
   111     {
   107       physical_lines: Array[Int],
       
   108       start: Array[Int],
       
   109       end: Array[Int],
       
   110       y: Int,
       
   111       line_height: Int
       
   112     ): Unit = {
   112       painter_rendering = get_rendering()
   113       painter_rendering = get_rendering()
   113       painter_clip = gfx.getClip
   114       painter_clip = gfx.getClip
   114       caret_focus =
   115       caret_focus =
   115         if (caret_enabled && !painter_rendering.snapshot.is_outdated) {
   116         if (caret_enabled && !painter_rendering.snapshot.is_outdated) {
   116           painter_rendering.caret_focus(JEdit_Lib.caret_range(text_area), caret_focus_range)
   117           painter_rendering.caret_focus(JEdit_Lib.caret_range(text_area), caret_focus_range)
   117         }
   118         }
   118         else Rendering.Focus.empty
   119         else Rendering.Focus.empty
   119     }
   120     }
   120   }
   121   }
   121 
   122 
   122   private val reset_state = new TextAreaExtension
   123   private val reset_state = new TextAreaExtension {
   123   {
   124     override def paintScreenLineRange(
   124     override def paintScreenLineRange(gfx: Graphics2D,
   125       gfx: Graphics2D,
   125       first_line: Int, last_line: Int, physical_lines: Array[Int],
   126       first_line: Int,
   126       start: Array[Int], end: Array[Int], y: Int, line_height: Int): Unit =
   127       last_line: Int,
   127     {
   128       physical_lines: Array[Int],
       
   129       start: Array[Int],
       
   130       end: Array[Int],
       
   131       y: Int,
       
   132       line_height: Int
       
   133     ): Unit = {
   128       painter_rendering = null
   134       painter_rendering = null
   129       painter_clip = null
   135       painter_clip = null
   130       caret_focus = Rendering.Focus.empty
   136       caret_focus = Rendering.Focus.empty
   131     }
   137     }
   132   }
   138   }
   133 
   139 
   134   def robust_rendering(body: JEdit_Rendering => Unit): Unit =
   140   def robust_rendering(body: JEdit_Rendering => Unit): Unit = {
   135   {
       
   136     robust_body(()) { body(painter_rendering) }
   141     robust_body(()) { body(painter_rendering) }
   137   }
   142   }
   138 
   143 
   139 
   144 
   140   /* active areas within the text */
   145   /* active areas within the text */
   141 
   146 
   142   private class Active_Area[A](
   147   private class Active_Area[A](
   143     rendering: JEdit_Rendering => Text.Range => Option[Text.Info[A]],
   148     rendering: JEdit_Rendering => Text.Range => Option[Text.Info[A]],
   144     cursor: Option[Int])
   149     cursor: Option[Int]
   145   {
   150   ) {
   146     private var the_text_info: Option[(String, Text.Info[A])] = None
   151     private var the_text_info: Option[(String, Text.Info[A])] = None
   147 
   152 
   148     def is_active: Boolean = the_text_info.isDefined
   153     def is_active: Boolean = the_text_info.isDefined
   149     def text_info: Option[(String, Text.Info[A])] = the_text_info
   154     def text_info: Option[(String, Text.Info[A])] = the_text_info
   150     def info: Option[Text.Info[A]] = the_text_info.map(_._2)
   155     def info: Option[Text.Info[A]] = the_text_info.map(_._2)
   151 
   156 
   152     def update(new_info: Option[Text.Info[A]]): Unit =
   157     def update(new_info: Option[Text.Info[A]]): Unit = {
   153     {
       
   154       val old_text_info = the_text_info
   158       val old_text_info = the_text_info
   155       val new_text_info =
   159       val new_text_info =
   156         new_info.map(info => (text_area.getText(info.range.start, info.range.length), info))
   160         new_info.map(info => (text_area.getText(info.range.start, info.range.length), info))
   157 
   161 
   158       if (new_text_info != old_text_info) {
   162       if (new_text_info != old_text_info) {
   208     override def windowIconified(e: WindowEvent): Unit = { robust_body(()) { active_reset() } }
   212     override def windowIconified(e: WindowEvent): Unit = { robust_body(()) { active_reset() } }
   209     override def windowDeactivated(e: WindowEvent): Unit = { robust_body(()) { active_reset() } }
   213     override def windowDeactivated(e: WindowEvent): Unit = { robust_body(()) { active_reset() } }
   210   }
   214   }
   211 
   215 
   212   private val mouse_listener = new MouseAdapter {
   216   private val mouse_listener = new MouseAdapter {
   213     override def mouseClicked(e: MouseEvent): Unit =
   217     override def mouseClicked(e: MouseEvent): Unit = {
   214     {
       
   215       robust_body(()) {
   218       robust_body(()) {
   216         hyperlink_area.info match {
   219         hyperlink_area.info match {
   217           case Some(Text.Info(range, link)) =>
   220           case Some(Text.Info(range, link)) =>
   218             if (!link.external) {
   221             if (!link.external) {
   219               try { text_area.moveCaretPosition(range.start) }
   222               try { text_area.moveCaretPosition(range.start) }
   245         SwingUtilities.convertPointFromScreen(point, painter)
   248         SwingUtilities.convertPointFromScreen(point, painter)
   246         painter.contains(point)
   249         painter.contains(point)
   247     }
   250     }
   248 
   251 
   249   private val mouse_motion_listener = new MouseMotionAdapter {
   252   private val mouse_motion_listener = new MouseMotionAdapter {
   250     override def mouseDragged(evt: MouseEvent): Unit =
   253     override def mouseDragged(evt: MouseEvent): Unit = {
   251     {
       
   252       robust_body(()) {
   254       robust_body(()) {
   253         active_reset()
   255         active_reset()
   254         Completion_Popup.Text_Area.dismissed(text_area)
   256         Completion_Popup.Text_Area.dismissed(text_area)
   255         Pretty_Tooltip.dismiss_descendant(text_area.getPainter)
   257         Pretty_Tooltip.dismiss_descendant(text_area.getPainter)
   256       }
   258       }
   257     }
   259     }
   258 
   260 
   259     override def mouseMoved(evt: MouseEvent): Unit =
   261     override def mouseMoved(evt: MouseEvent): Unit = {
   260     {
       
   261       robust_body(()) {
   262       robust_body(()) {
   262         val x = evt.getX
   263         val x = evt.getX
   263         val y = evt.getY
   264         val y = evt.getY
   264         val control = JEdit_Lib.command_modifier(evt)
   265         val control = JEdit_Lib.command_modifier(evt)
   265 
   266 
   267           JEdit_Lib.buffer_lock(buffer) {
   268           JEdit_Lib.buffer_lock(buffer) {
   268             JEdit_Lib.pixel_range(text_area, x, y) match {
   269             JEdit_Lib.pixel_range(text_area, x, y) match {
   269               case None => active_reset()
   270               case None => active_reset()
   270               case Some(range) =>
   271               case Some(range) =>
   271                 val rendering = get_rendering()
   272                 val rendering = get_rendering()
   272                 for ((area, require_control) <- active_areas)
   273                 for ((area, require_control) <- active_areas) {
   273                 {
       
   274                   if (control == require_control && !rendering.snapshot.is_outdated)
   274                   if (control == require_control && !rendering.snapshot.is_outdated)
   275                     area.update_rendering(rendering, range)
   275                     area.update_rendering(rendering, range)
   276                   else area.reset()
   276                   else area.reset()
   277                 }
   277                 }
   278             }
   278             }
   308   }
   308   }
   309 
   309 
   310 
   310 
   311   /* text background */
   311   /* text background */
   312 
   312 
   313   private val background_painter = new TextAreaExtension
   313   private val background_painter = new TextAreaExtension {
   314   {
   314     override def paintScreenLineRange(
   315     override def paintScreenLineRange(gfx: Graphics2D,
   315       gfx: Graphics2D,
   316       first_line: Int, last_line: Int, physical_lines: Array[Int],
   316       first_line: Int,
   317       start: Array[Int], end: Array[Int], y: Int, line_height: Int): Unit =
   317       last_line: Int,
   318     {
   318       physical_lines: Array[Int],
       
   319       start: Array[Int],
       
   320       end: Array[Int],
       
   321       y: Int,
       
   322       line_height: Int
       
   323     ): Unit = {
   319       robust_rendering { rendering =>
   324       robust_rendering { rendering =>
   320         val fm = text_area.getPainter.getFontMetrics
   325         val fm = text_area.getPainter.getFontMetrics
   321 
   326 
   322         for (i <- physical_lines.indices) {
   327         for (i <- physical_lines.indices) {
   323           if (physical_lines(i) != -1) {
   328           if (physical_lines(i) != -1) {
   324             val line_range = Text.Range(start(i), end(i) min buffer.getLength)
   329             val line_range = Text.Range(start(i), end(i) min buffer.getLength)
   325 
   330 
   326             // line background color
   331             // line background color
   327             for { (c, separator) <- rendering.line_background(line_range) }
   332             for { (c, separator) <- rendering.line_background(line_range) } {
   328             {
       
   329               gfx.setColor(rendering.color(c))
   333               gfx.setColor(rendering.color(c))
   330               val sep = if (separator) 2 min (line_height / 2) else 0
   334               val sep = if (separator) 2 min (line_height / 2) else 0
   331               gfx.fillRect(0, y + i * line_height, text_area.getWidth, line_height - sep)
   335               gfx.fillRect(0, y + i * line_height, text_area.getWidth, line_height - sep)
   332             }
   336             }
   333 
   337 
   387   /* text */
   391   /* text */
   388 
   392 
   389   private def caret_enabled: Boolean =
   393   private def caret_enabled: Boolean =
   390     caret_visible && (!text_area.hasFocus || text_area.isCaretVisible)
   394     caret_visible && (!text_area.hasFocus || text_area.isCaretVisible)
   391 
   395 
   392   private def caret_color(rendering: JEdit_Rendering, offset: Text.Offset): Color =
   396   private def caret_color(rendering: JEdit_Rendering, offset: Text.Offset): Color = {
   393   {
       
   394     if (text_area.isCaretVisible) text_area.getPainter.getCaretColor
   397     if (text_area.isCaretVisible) text_area.getPainter.getCaretColor
   395     else {
   398     else {
   396       val debug_positions =
   399       val debug_positions =
   397         (for {
   400         (for {
   398           c <- PIDE.session.debugger.focus().iterator
   401           c <- PIDE.session.debugger.focus().iterator
   402         rendering.caret_debugger_color
   405         rendering.caret_debugger_color
   403       else rendering.caret_invisible_color
   406       else rendering.caret_invisible_color
   404     }
   407     }
   405   }
   408   }
   406 
   409 
   407   private class Font_Subst
   410   private class Font_Subst {
   408   {
       
   409     private var cache = Map.empty[Int, Option[Font]]
   411     private var cache = Map.empty[Int, Option[Font]]
   410 
   412 
   411     def get(codepoint: Int): Option[Font] =
   413     def get(codepoint: Int): Option[Font] =
   412       cache.getOrElse(codepoint,
   414       cache.getOrElse(codepoint,
   413         {
   415         {
   418           cache += (codepoint -> res)
   420           cache += (codepoint -> res)
   419           res
   421           res
   420         })
   422         })
   421   }
   423   }
   422 
   424 
   423   private def paint_chunk_list(rendering: JEdit_Rendering, font_subst: Font_Subst,
   425   private def paint_chunk_list(
   424     gfx: Graphics2D, line_start: Text.Offset, head: Chunk, x: Float, y: Float): Float =
   426     rendering: JEdit_Rendering,
   425   {
   427     font_subst: Font_Subst,
       
   428     gfx: Graphics2D,
       
   429     line_start: Text.Offset,
       
   430     head: Chunk,
       
   431     x: Float,
       
   432     y: Float
       
   433   ): Float = {
   426     val clip_rect = gfx.getClipBounds
   434     val clip_rect = gfx.getClipBounds
   427 
   435 
   428     val caret_range =
   436     val caret_range =
   429       if (caret_enabled) JEdit_Lib.caret_range(text_area)
   437       if (caret_enabled) JEdit_Lib.caret_range(text_area)
   430       else Text.Range.offside
   438       else Text.Range.offside
   432     var w = 0.0f
   440     var w = 0.0f
   433     var chunk = head
   441     var chunk = head
   434     while (chunk != null) {
   442     while (chunk != null) {
   435       val chunk_offset = line_start + chunk.offset
   443       val chunk_offset = line_start + chunk.offset
   436       if (x + w + chunk.width > clip_rect.x &&
   444       if (x + w + chunk.width > clip_rect.x &&
   437           x + w < clip_rect.x + clip_rect.width && chunk.length > 0)
   445           x + w < clip_rect.x + clip_rect.width && chunk.length > 0) {
   438       {
       
   439         val chunk_range = Text.Range(chunk_offset, chunk_offset + chunk.length)
   446         val chunk_range = Text.Range(chunk_offset, chunk_offset + chunk.length)
   440         val chunk_str =
   447         val chunk_str =
   441           if (chunk.chars == null) Symbol.spaces(chunk.length)
   448           if (chunk.chars == null) Symbol.spaces(chunk.length)
   442           else {
   449           else {
   443             if (chunk.str == null) { chunk.str = new String(chunk.chars) }
   450             if (chunk.str == null) { chunk.str = new String(chunk.chars) }
   484       chunk = chunk.next.asInstanceOf[Chunk]
   491       chunk = chunk.next.asInstanceOf[Chunk]
   485     }
   492     }
   486     w
   493     w
   487   }
   494   }
   488 
   495 
   489   private val text_painter = new TextAreaExtension
   496   private val text_painter = new TextAreaExtension {
   490   {
   497     override def paintScreenLineRange(
   491     override def paintScreenLineRange(gfx: Graphics2D,
   498       gfx: Graphics2D,
   492       first_line: Int, last_line: Int, physical_lines: Array[Int],
   499       first_line: Int,
   493       start: Array[Int], end: Array[Int], y: Int, line_height: Int): Unit =
   500       last_line: Int,
   494     {
   501       physical_lines: Array[Int],
       
   502       start: Array[Int],
       
   503       end: Array[Int],
       
   504       y: Int,
       
   505       line_height: Int
       
   506     ): Unit = {
   495       robust_rendering { rendering =>
   507       robust_rendering { rendering =>
   496         val painter = text_area.getPainter
   508         val painter = text_area.getPainter
   497         val fm = painter.getFontMetrics
   509         val fm = painter.getFontMetrics
   498         val lm = painter.getFont.getLineMetrics(" ", painter.getFontRenderContext)
   510         val lm = painter.getFont.getLineMetrics(" ", painter.getFontRenderContext)
   499 
   511 
   500         val clip = gfx.getClip
   512         val clip = gfx.getClip
   501         val x0 = text_area.getHorizontalOffset
   513         val x0 = text_area.getHorizontalOffset
   502         var y0 = y + painter.getLineHeight - (fm.getLeading + 1) - fm.getDescent
   514         var y0 = y + painter.getLineHeight - (fm.getLeading + 1) - fm.getDescent
   503 
   515 
   504         val (bullet_x, bullet_y, bullet_w, bullet_h) =
   516         val (bullet_x, bullet_y, bullet_w, bullet_h) = {
   505         {
       
   506           val w = fm.charWidth(' ')
   517           val w = fm.charWidth(' ')
   507           val b = (w / 2) max 1
   518           val b = (w / 2) max 1
   508           val c = (lm.getAscent + lm.getStrikethroughOffset).round
   519           val c = (lm.getAscent + lm.getStrikethroughOffset).round
   509           ((w - b + 1) / 2, c - b / 2, w - b, line_height - b)
   520           ((w - b + 1) / 2, c - b / 2, w - b, line_height - b)
   510         }
   521         }
   549   }
   560   }
   550 
   561 
   551 
   562 
   552   /* foreground */
   563   /* foreground */
   553 
   564 
   554   private val foreground_painter = new TextAreaExtension
   565   private val foreground_painter = new TextAreaExtension {
   555   {
   566     override def paintScreenLineRange(
   556     override def paintScreenLineRange(gfx: Graphics2D,
   567       gfx: Graphics2D,
   557       first_line: Int, last_line: Int, physical_lines: Array[Int],
   568       first_line: Int,
   558       start: Array[Int], end: Array[Int], y: Int, line_height: Int): Unit =
   569       last_line: Int,
   559     {
   570       physical_lines: Array[Int],
       
   571       start: Array[Int],
       
   572       end: Array[Int],
       
   573       y: Int,
       
   574       line_height: Int
       
   575     ): Unit = {
   560       robust_rendering { rendering =>
   576       robust_rendering { rendering =>
   561         val search_pattern = get_search_pattern()
   577         val search_pattern = get_search_pattern()
   562         for (i <- physical_lines.indices) {
   578         for (i <- physical_lines.indices) {
   563           if (physical_lines(i) != -1) {
   579           if (physical_lines(i) != -1) {
   564             val line_range = Text.Range(start(i), end(i) min buffer.getLength)
   580             val line_range = Text.Range(start(i), end(i) min buffer.getLength)
   633   }
   649   }
   634 
   650 
   635 
   651 
   636   /* caret -- outside of text range */
   652   /* caret -- outside of text range */
   637 
   653 
   638   private class Caret_Painter(before: Boolean) extends TextAreaExtension
   654   private class Caret_Painter(before: Boolean) extends TextAreaExtension {
   639   {
   655     override def paintValidLine(
   640     override def paintValidLine(gfx: Graphics2D,
   656       gfx: Graphics2D,
   641       screen_line: Int, physical_line: Int, start: Int, end: Int, y: Int): Unit =
   657       screen_line: Int,
   642     {
   658       physical_line: Int,
       
   659       start: Int,
       
   660       end: Int,
       
   661       y: Int
       
   662     ): Unit = {
   643       robust_rendering { _ =>
   663       robust_rendering { _ =>
   644         if (before) gfx.clipRect(0, 0, 0, 0)
   664         if (before) gfx.clipRect(0, 0, 0, 0)
   645         else gfx.setClip(painter_clip)
   665         else gfx.setClip(painter_clip)
   646       }
   666       }
   647     }
   667     }
   650   private val before_caret_painter1 = new Caret_Painter(true)
   670   private val before_caret_painter1 = new Caret_Painter(true)
   651   private val after_caret_painter1 = new Caret_Painter(false)
   671   private val after_caret_painter1 = new Caret_Painter(false)
   652   private val before_caret_painter2 = new Caret_Painter(true)
   672   private val before_caret_painter2 = new Caret_Painter(true)
   653   private val after_caret_painter2 = new Caret_Painter(false)
   673   private val after_caret_painter2 = new Caret_Painter(false)
   654 
   674 
   655   private val caret_painter = new TextAreaExtension
   675   private val caret_painter = new TextAreaExtension {
   656   {
   676     override def paintValidLine(
   657     override def paintValidLine(gfx: Graphics2D,
   677       gfx: Graphics2D,
   658       screen_line: Int, physical_line: Int, start: Int, end: Int, y: Int): Unit =
   678       screen_line: Int,
   659     {
   679       physical_line: Int,
       
   680       start: Int,
       
   681       end: Int,
       
   682       y: Int
       
   683     ): Unit = {
   660       robust_rendering { rendering =>
   684       robust_rendering { rendering =>
   661         if (caret_visible) {
   685         if (caret_visible) {
   662           val caret = text_area.getCaretPosition
   686           val caret = text_area.getCaretPosition
   663           if (caret_enabled && start <= caret && caret == end - 1) {
   687           if (caret_enabled && start <= caret && caret == end - 1) {
   664             val painter = text_area.getPainter
   688             val painter = text_area.getPainter
   686   }
   710   }
   687 
   711 
   688 
   712 
   689   /* activation */
   713   /* activation */
   690 
   714 
   691   def activate(): Unit =
   715   def activate(): Unit = {
   692   {
       
   693     val painter = text_area.getPainter
   716     val painter = text_area.getPainter
   694     painter.addExtension(TextAreaPainter.LOWEST_LAYER, set_state)
   717     painter.addExtension(TextAreaPainter.LOWEST_LAYER, set_state)
   695     painter.addExtension(TextAreaPainter.LINE_BACKGROUND_LAYER + 1, background_painter)
   718     painter.addExtension(TextAreaPainter.LINE_BACKGROUND_LAYER + 1, background_painter)
   696     painter.addExtension(TextAreaPainter.TEXT_LAYER, text_painter)
   719     painter.addExtension(TextAreaPainter.TEXT_LAYER, text_painter)
   697     painter.addExtension(TextAreaPainter.CARET_LAYER - 1, before_caret_painter1)
   720     painter.addExtension(TextAreaPainter.CARET_LAYER - 1, before_caret_painter1)
   707     text_area.addKeyListener(key_listener)
   730     text_area.addKeyListener(key_listener)
   708     text_area.addFocusListener(focus_listener)
   731     text_area.addFocusListener(focus_listener)
   709     view.addWindowListener(window_listener)
   732     view.addWindowListener(window_listener)
   710   }
   733   }
   711 
   734 
   712   def deactivate(): Unit =
   735   def deactivate(): Unit = {
   713   {
       
   714     active_reset()
   736     active_reset()
   715     val painter = text_area.getPainter
   737     val painter = text_area.getPainter
   716     view.removeWindowListener(window_listener)
   738     view.removeWindowListener(window_listener)
   717     text_area.removeFocusListener(focus_listener)
   739     text_area.removeFocusListener(focus_listener)
   718     text_area.removeKeyListener(key_listener)
   740     text_area.removeKeyListener(key_listener)