src/Pure/PIDE/rendering.scala
changeset 83174 bf352fc004bc
parent 83173 74f51d5dd7fe
child 83176 a2a49ba7a6d1
equal deleted inserted replaced
83173:74f51d5dd7fe 83174:bf352fc004bc
   266     Markup.Elements(Markup.NOTATION, Markup.EXPRESSION, Markup.LANGUAGE, Markup.ML_TYPING,
   266     Markup.Elements(Markup.NOTATION, Markup.EXPRESSION, Markup.LANGUAGE, Markup.ML_TYPING,
   267       Markup.MARKDOWN_PARAGRAPH, Markup.MARKDOWN_ITEM, Markup.Markdown_List.name, Markup.ENTITY,
   267       Markup.MARKDOWN_PARAGRAPH, Markup.MARKDOWN_ITEM, Markup.Markdown_List.name, Markup.ENTITY,
   268       Markup.COMMAND_SPAN)
   268       Markup.COMMAND_SPAN)
   269 
   269 
   270   val tooltip_elements: Markup.Elements =
   270   val tooltip_elements: Markup.Elements =
   271     Markup.Elements(Markup.LANGUAGE, Markup.NOTATION, Markup.EXPRESSION, Markup.TIMING,
   271     Markup.Elements(Markup.LANGUAGE, Markup.NOTATION, Markup.EXPRESSION,
   272       Markup.ENTITY, Markup.SORTING, Markup.TYPING, Markup.CLASS_PARAMETER, Markup.ML_TYPING,
   272       Markup.ENTITY, Markup.SORTING, Markup.TYPING, Markup.CLASS_PARAMETER, Markup.ML_TYPING,
   273       Markup.ML_BREAKPOINT, Markup.PATH, Markup.DOC, Markup.URL, Markup.COMMAND_SPAN,
   273       Markup.ML_BREAKPOINT, Markup.PATH, Markup.DOC, Markup.URL, Markup.COMMAND_SPAN,
   274       Markup.MARKDOWN_PARAGRAPH, Markup.MARKDOWN_ITEM, Markup.Markdown_List.name) ++
   274       Markup.MARKDOWN_PARAGRAPH, Markup.MARKDOWN_ITEM, Markup.Markdown_List.name) ++
   275       Markup.Elements(tooltip_description.keySet)
   275       Markup.Elements(tooltip_description.keySet)
   276 
   276 
   619 
   619 
   620   def timing_threshold: Double = options.real("editor_timing_threshold")
   620   def timing_threshold: Double = options.real("editor_timing_threshold")
   621 
   621 
   622   private sealed case class Tooltip_Info(
   622   private sealed case class Tooltip_Info(
   623     range: Text.Range,
   623     range: Text.Range,
   624     timing: Timing = Timing.zero,
       
   625     messages: List[(Long, XML.Elem)] = Nil,
   624     messages: List[(Long, XML.Elem)] = Nil,
   626     rev_infos: List[(Boolean, Int, XML.Elem)] = Nil
   625     rev_infos: List[(Boolean, Int, XML.Elem)] = Nil
   627   ) {
   626   ) {
   628     def add_timing(t: Timing): Tooltip_Info = copy(timing = timing + t)
       
   629     def add_message(r0: Text.Range, serial: Long, msg: XML.Elem): Tooltip_Info = {
   627     def add_message(r0: Text.Range, serial: Long, msg: XML.Elem): Tooltip_Info = {
   630       val r = snapshot.convert(r0)
   628       val r = snapshot.convert(r0)
   631       if (range == r) copy(messages = (serial -> msg) :: messages)
   629       if (range == r) copy(messages = (serial -> msg) :: messages)
   632       else copy(range = r, messages = List(serial -> msg))
   630       else copy(range = r, messages = List(serial -> msg))
   633     }
   631     }
   641       else copy (range = r, rev_infos = List(entry))
   639       else copy (range = r, rev_infos = List(entry))
   642     }
   640     }
   643     def add_info_text(r0: Text.Range, text: String, ord: Int = 0): Tooltip_Info =
   641     def add_info_text(r0: Text.Range, text: String, ord: Int = 0): Tooltip_Info =
   644       add_info(r0, Pretty.string(text), ord = ord)
   642       add_info(r0, Pretty.string(text), ord = ord)
   645 
   643 
   646     def timing_info(elem: XML.Elem): Option[XML.Elem] =
       
   647       if (elem.markup.name == Markup.TIMING) {
       
   648         if (timing.is_relevant && timing.elapsed.seconds >= timing_threshold) {
       
   649           Some(Pretty.string(timing.message))
       
   650         }
       
   651         else None
       
   652       }
       
   653       else Some(elem)
       
   654     def infos(important: Boolean = true): List[XML.Elem] =
   644     def infos(important: Boolean = true): List[XML.Elem] =
   655       for {
   645       for ((imp, _, elem) <- rev_infos.reverse.sortBy(_._2) if imp == important) yield elem
   656         (is_important, _, elem) <- rev_infos.reverse.sortBy(_._2) if is_important == important
       
   657         elem1 <- timing_info(elem)
       
   658       } yield elem1
       
   659   }
   646   }
   660 
   647 
   661   def perhaps_append_file(node_name: Document.Node.Name, name: String): String =
   648   def perhaps_append_file(node_name: Document.Node.Name, name: String): String =
   662     if (Path.is_valid(name)) session.resources.append_path(node_name.master_dir, Path.explode(name))
   649     if (Path.is_valid(name)) session.resources.append_path(node_name.master_dir, Path.explode(name))
   663     else name
   650     else name
   664 
   651 
   665   def tooltips(elements: Markup.Elements, range: Text.Range): Option[Text.Info[List[XML.Elem]]] = {
   652   def tooltips(elements: Markup.Elements, range: Text.Range): Option[Text.Info[List[XML.Elem]]] = {
   666     val results =
   653     val results =
   667       snapshot.cumulate[Tooltip_Info](range, Tooltip_Info(range), elements, command_states =>
   654       snapshot.cumulate[Tooltip_Info](range, Tooltip_Info(range), elements, command_states =>
   668         {
   655         {
   669           case (info, Text.Info(_, XML.Elem(Markup.Timing(t), _))) => Some(info.add_timing(t))
       
   670 
       
   671           case (info, Text.Info(r0, msg @ XML.Elem(Markup.Bad(i), body)))
   656           case (info, Text.Info(r0, msg @ XML.Elem(Markup.Bad(i), body)))
   672           if body.nonEmpty => Some(info.add_message(r0, i, msg))
   657           if body.nonEmpty => Some(info.add_message(r0, i, msg))
   673 
   658 
   674           case (info, Text.Info(r0, XML.Elem(Markup(name, props), _)))
   659           case (info, Text.Info(r0, XML.Elem(Markup(name, props), _)))
   675           if Rendering.tooltip_message_elements(name) =>
   660           if Rendering.tooltip_message_elements(name) =>
   678 
   663 
   679           case (info, Text.Info(r0, XML.Elem(Markup.Entity(kind, name), _)))
   664           case (info, Text.Info(r0, XML.Elem(Markup.Entity(kind, name), _)))
   680           if kind != "" && kind != Markup.ML_DEF =>
   665           if kind != "" && kind != Markup.ML_DEF =>
   681             val txt = Rendering.gui_name(name, kind = kind)
   666             val txt = Rendering.gui_name(name, kind = kind)
   682             val info1 = info.add_info_text(r0, txt, ord = 2)
   667             val info1 = info.add_info_text(r0, txt, ord = 2)
   683             Some(if (kind == Markup.COMMAND) info1.add_info(r0, XML.elem(Markup.TIMING)) else info1)
   668             val info2 =
       
   669               if (kind == Markup.COMMAND) {
       
   670                 val timing = Timing.merge(command_states.iterator.map(_.timing))
       
   671                 if (timing.is_relevant && timing.elapsed.seconds >= timing_threshold) {
       
   672                   info1.add_info(r0, Pretty.string(timing.message))
       
   673                 }
       
   674                 else info1
       
   675               }
       
   676               else info1
       
   677             Some(info2)
   684 
   678 
   685           case (info, Text.Info(r0, XML.Elem(Markup.Path(name), _))) =>
   679           case (info, Text.Info(r0, XML.Elem(Markup.Path(name), _))) =>
   686             val file = perhaps_append_file(snapshot.node_name, name)
   680             val file = perhaps_append_file(snapshot.node_name, name)
   687             val info1 =
   681             val info1 =
   688               if (name == file) info
   682               if (name == file) info