diff --git a/src/Tools/jEdit/etc/options b/src/Tools/jEdit/etc/options --- a/src/Tools/jEdit/etc/options +++ b/src/Tools/jEdit/etc/options @@ -1,167 +1,169 @@ (* :mode=isabelle-options: *) public option jedit_logic : string = "" -- "default logic session" public option jedit_print_mode : string = "" -- "default print modes for output, separated by commas (change requires restart)" public option jedit_auto_resolve : bool = false -- "automatically resolve auxiliary files within the document model" public option jedit_reset_font_size : int = 18 -- "reset main text font size" public option jedit_font_scale : real = 1.0 -- "scale factor of add-on panels wrt. main text font" public option jedit_popup_font_scale : real = 0.85 -- "scale factor of popups wrt. main text font" public option jedit_popup_bounds : real = 0.5 -- "relative bounds of popup window wrt. logical screen size" public option jedit_tooltip_delay : real = 0.75 -- "open/close delay for document tooltips (seconds)" public option jedit_tooltip_margin : int = 60 -- "margin for tooltip pretty-printing" public option jedit_structure_limit : int = 1000 -- "maximum number of lines to scan for language structure" public option jedit_symbols_search_limit : int = 50 -- "maximum number of symbols in search result" public option jedit_timing_threshold : real = 0.1 -- "default threshold for timing display (seconds)" public option jedit_text_overview : bool = true -- "paint text overview column" public option jedit_focus_modifier : string = "CS" -- "keyboard modifier to enable entity focus regardless of def visibility" public option jedit_toggle_full_screen : bool = false -- "use original jEdit action toggle-full-screen instead of Isabelle/jEdit variant" public option isabelle_fonts_hinted : bool = true -- "use hinted Isabelle DejaVu fonts (change requires restart)" section "Indentation" public option jedit_indent_input : bool = true -- "indentation of Isabelle keywords after input (typed character or completion)" public option jedit_indent_newline : bool = true -- "indentation of Isabelle keywords on ENTER (action isabelle.newline)" public option jedit_indent_script : bool = true -- "indent unstructured proof script ('apply' etc.) via number of subgoals" public option jedit_indent_script_limit : int = 20 -- "maximum indentation of unstructured proof script ('apply' etc.)" section "Completion" public option jedit_completion : bool = true -- "enable completion popup" public option jedit_completion_select_enter : bool = false -- "select completion item via ENTER" public option jedit_completion_select_tab : bool = true -- "select completion item via TAB" public option jedit_completion_context : bool = true -- "use semantic language context for completion" public option jedit_completion_delay : real = 0.5 -- "delay for completion popup (seconds)" public option jedit_completion_immediate : bool = true -- "insert uniquely completed abbreviation immediately into buffer" section "Rendering of Document Content" option outdated_color : string = "EEE3E3FF" option unprocessed_color : string = "FFA0A0FF" option unprocessed1_color : string = "FFA0A032" option running_color : string = "610061FF" option running1_color : string = "61006164" option bullet_color : string = "000000FF" option tooltip_color : string = "FFFFE9FF" option writeln_color : string = "C0C0C0FF" option information_color : string = "C1DFEEFF" option warning_color : string = "FF8C00FF" option legacy_color : string = "FF8C00FF" option error_color : string = "B22222FF" +option ok_color : string = "000000FF" +option failed_color : string = "B22222FF" option writeln_message_color : string = "F0F0F0FF" option information_message_color : string = "DCEAF3FF" option tracing_message_color : string = "F0F8FFFF" option warning_message_color : string = "EEE8AAFF" option legacy_message_color : string = "EEE8AAFF" option error_message_color : string = "FFC1C1FF" option spell_checker_color : string = "0000FFFF" option bad_color : string = "FF6A6A64" option canceled_color : string = "FF6A6A64" option intensify_color : string = "FFCC6664" option entity_color : string = "CCD9FF80" option entity_ref_color : string = "800080FF" option breakpoint_disabled_color : string = "CCCC0080" option breakpoint_enabled_color : string = "FF9966FF" option quoted_color : string = "8B8B8B19" option antiquoted_color : string = "FFC83219" option antiquote_color : string = "6600CCFF" option raw_text_color : string = "6600CCFF" option plain_text_color : string = "CC6600FF" option highlight_color : string = "50505032" option hyperlink_color : string = "000000FF" option active_color : string = "DCDCDCFF" option active_hover_color : string = "9DC75DFF" option active_result_color : string = "999966FF" option keyword1_color : string = "006699FF" option keyword2_color : string = "009966FF" option keyword3_color : string = "0099FFFF" option quasi_keyword_color : string = "9966FFFF" option improper_color : string = "FF5050FF" option operator_color : string = "323232FF" option comment1_color : string = "CC0000FF" option comment2_color : string = "FF8400FF" option comment3_color : string = "6600CCFF" option caret_debugger_color : string = "FF9966FF" option caret_invisible_color : string = "50000080" option completion_color : string = "0000FFFF" option search_color : string = "66FFFF64" option tfree_color : string = "A020F0FF" option tvar_color : string = "A020F0FF" option free_color : string = "0000FFFF" option skolem_color : string = "D2691EFF" option bound_color : string = "008000FF" option var_color : string = "00009BFF" option inner_numeral_color : string = "FF0000FF" option inner_quoted_color : string = "FF00CCFF" option inner_cartouche_color : string = "CC6600FF" option dynamic_color : string = "7BA428FF" option class_parameter_color : string = "D2691EFF" option markdown_bullet1_color : string = "DAFEDAFF" option markdown_bullet2_color : string = "FFF0CCFF" option markdown_bullet3_color : string = "E7E7FFFF" option markdown_bullet4_color : string = "FFE0F0FF" section "Icons" option tooltip_close_icon : string = "idea-icons/actions/closeHovered.png" option tooltip_detach_icon : string = "idea-icons/actions/nextfile.png" option gutter_information_icon : string = "idea-icons/general/balloonInformation.png" option gutter_warning_icon : string = "idea-icons/runConfigurations/testFailed.png" option gutter_legacy_icon : string = "idea-icons/general/balloonWarning.png" option gutter_error_icon : string = "idea-icons/runConfigurations/testError.png" option process_passive_icon : string = "idea-icons/process/step_passive.png" option process_active_icons : string = "idea-icons/process/step_1.png:idea-icons/process/step_2.png:idea-icons/process/step_3.png:idea-icons/process/step_4.png:idea-icons/process/step_5.png:idea-icons/process/step_6.png:idea-icons/process/step_7.png:idea-icons/process/step_8.png:idea-icons/process/step_9.png:idea-icons/process/step_10.png:idea-icons/process/step_11.png:idea-icons/process/step_12.png" diff --git a/src/Tools/jEdit/src/theories_dockable.scala b/src/Tools/jEdit/src/theories_dockable.scala --- a/src/Tools/jEdit/src/theories_dockable.scala +++ b/src/Tools/jEdit/src/theories_dockable.scala @@ -1,271 +1,275 @@ /* Title: Tools/jEdit/src/theories_dockable.scala Author: Makarius Dockable window for theories managed by prover. */ package isabelle.jedit import isabelle._ import isabelle.jedit_base.Dockable import scala.swing.{Button, TextArea, Label, ListView, Alignment, ScrollPane, Component, CheckBox, BorderPanel} import scala.swing.event.{ButtonClicked, MouseClicked, MouseMoved} import java.awt.{BorderLayout, Graphics2D, Color, Point, Dimension} import javax.swing.{JList, BorderFactory, UIManager} import javax.swing.border.{BevelBorder, SoftBevelBorder} import org.gjt.sp.jedit.{View, jEdit} class Theories_Dockable(view: View, position: String) extends Dockable(view, position) { /* status */ private val status = new ListView(List.empty[Document.Node.Name]) { background = { // enforce default value val c = UIManager.getDefaults.getColor("Panel.background") new Color(c.getRed, c.getGreen, c.getBlue, c.getAlpha) } listenTo(mouse.clicks) listenTo(mouse.moves) reactions += { case MouseClicked(_, point, _, clicks, _) => val index = peer.locationToIndex(point) if (index >= 0) { if (in_checkbox(peer.indexToLocation(index), point)) { if (clicks == 1) Document_Model.node_required(listData(index), toggle = true) } else if (clicks == 2) PIDE.editor.goto_file(true, view, listData(index).node) } case MouseMoved(_, point, _) => val index = peer.locationToIndex(point) val index_location = peer.indexToLocation(index) if (index >= 0 && in_checkbox(index_location, point)) tooltip = "Mark as required for continuous checking" else if (index >= 0 && in_label(index_location, point)) { val name = listData(index) val st = nodes_status.overall_node_status(name) tooltip = "theory " + quote(name.theory) + (if (st == Document_Status.Overall_Node_Status.ok) "" else " (" + st + ")") } else tooltip = null } } status.peer.setLayoutOrientation(JList.HORIZONTAL_WRAP) status.peer.setVisibleRowCount(0) status.selection.intervalMode = ListView.IntervalMode.Single set_content(new ScrollPane(status)) /* controls */ def phase_text(phase: Session.Phase): String = "Prover: " + phase.print private val session_phase = new Label(phase_text(PIDE.session.phase)) session_phase.border = new SoftBevelBorder(BevelBorder.LOWERED) session_phase.tooltip = "Status of prover session" private def handle_phase(phase: Session.Phase): Unit = { GUI_Thread.require {} session_phase.text = " " + phase_text(phase) + " " } private val purge = new Button("Purge") { tooltip = "Restrict document model to theories required for open editor buffers" reactions += { case ButtonClicked(_) => PIDE.editor.purge() } } private val continuous_checking = new Isabelle.Continuous_Checking continuous_checking.focusable = false private val logic = JEdit_Sessions.logic_selector(PIDE.options, true) private val controls = Wrap_Panel(List(purge, continuous_checking, session_phase, logic)) add(controls.peer, BorderLayout.NORTH) /* component state -- owned by GUI thread */ private var nodes_status = Document_Status.Nodes_Status.empty private var nodes_required: Set[Document.Node.Name] = Document_Model.required_nodes() private def in(geometry: Option[(Point, Dimension)], loc0: Point, p: Point): Boolean = geometry match { case Some((loc, size)) => loc0.x + loc.x <= p.x && p.x < loc0.x + size.width && loc0.y + loc.y <= p.y && p.y < loc0.y + size.height case None => false } private def in_checkbox(loc0: Point, p: Point): Boolean = Node_Renderer_Component != null && in(Node_Renderer_Component.checkbox_geometry, loc0, p) private def in_label(loc0: Point, p: Point): Boolean = Node_Renderer_Component != null && in(Node_Renderer_Component.label_geometry, loc0, p) private object Node_Renderer_Component extends BorderPanel { opaque = true border = BorderFactory.createEmptyBorder(2, 2, 2, 2) var node_name = Document.Node.Name.empty var checkbox_geometry: Option[(Point, Dimension)] = None val checkbox = new CheckBox { opaque = false override def paintComponent(gfx: Graphics2D): Unit = { super.paintComponent(gfx) if (location != null && size != null) checkbox_geometry = Some((location, size)) } } var label_geometry: Option[(Point, Dimension)] = None val label = new Label { background = view.getTextArea.getPainter.getBackground foreground = view.getTextArea.getPainter.getForeground opaque = false xAlignment = Alignment.Leading override def paintComponent(gfx: Graphics2D): Unit = { def paint_segment(x: Int, w: Int, color: Color): Unit = { gfx.setColor(color) gfx.fillRect(x, 0, w, size.height) } paint_segment(0, size.width, background) nodes_status.get(node_name) match { case Some(node_status) => val segments = List( (node_status.unprocessed, PIDE.options.color_value("unprocessed1_color")), (node_status.running, PIDE.options.color_value("running_color")), (node_status.warned, PIDE.options.color_value("warning_color")), (node_status.failed, PIDE.options.color_value("error_color")) ).filter(_._1 > 0) segments.foldLeft(size.width - 2) { case (last, (n, color)) => val w = (n * ((size.width - 4) - segments.length) / node_status.total) max 4 paint_segment(last - w, w, color) last - w - 1 } case None => paint_segment(0, size.width, PIDE.options.color_value("unprocessed1_color")) } super.paintComponent(gfx) if (location != null && size != null) label_geometry = Some((location, size)) } } def label_border(name: Document.Node.Name): Unit = { val st = nodes_status.overall_node_status(name) val color = - if (st == Document_Status.Overall_Node_Status.failed) - PIDE.options.color_value("error_color") - else label.foreground - val thickness1 = if (st == Document_Status.Overall_Node_Status.pending) 1 else 2 - val thickness2 = 3 - thickness1 + st match { + case Document_Status.Overall_Node_Status.ok => + PIDE.options.color_value("ok_color") + case Document_Status.Overall_Node_Status.failed => + PIDE.options.color_value("failed_color") + case _ => label.foreground + } + val thickness1 = if (st == Document_Status.Overall_Node_Status.pending) 1 else 3 + val thickness2 = 4 - thickness1 label.border = BorderFactory.createCompoundBorder( BorderFactory.createLineBorder(color, thickness1), BorderFactory.createEmptyBorder(thickness2, thickness2, thickness2, thickness2)) } layout(checkbox) = BorderPanel.Position.West layout(label) = BorderPanel.Position.Center } private class Node_Renderer extends ListView.Renderer[Document.Node.Name] { def componentFor(list: ListView[_ <: isabelle.Document.Node.Name], isSelected: Boolean, focused: Boolean, name: Document.Node.Name, index: Int): Component = { val component = Node_Renderer_Component component.node_name = name component.checkbox.selected = nodes_required.contains(name) component.label_border(name) component.label.text = name.theory_base_name component } } status.renderer = new Node_Renderer private def handle_update( domain: Option[Set[Document.Node.Name]] = None, trim: Boolean = false): Unit = { GUI_Thread.require {} val snapshot = PIDE.session.snapshot() val (nodes_status_changed, nodes_status1) = nodes_status.update( PIDE.resources, snapshot.state, snapshot.version, domain = domain, trim = trim) nodes_status = nodes_status1 if (nodes_status_changed) { status.listData = (for { (name, node_status) <- nodes_status1.present.iterator if !node_status.is_suppressed && node_status.total > 0 } yield name).toList } } /* main */ private val main = Session.Consumer[Any](getClass.getName) { case phase: Session.Phase => GUI_Thread.later { handle_phase(phase) } case _: Session.Global_Options => GUI_Thread.later { continuous_checking.load() logic.load () nodes_required = Document_Model.required_nodes() status.repaint() } case changed: Session.Commands_Changed => GUI_Thread.later { handle_update(domain = Some(changed.nodes), trim = changed.assignment) } } override def init(): Unit = { PIDE.session.phase_changed += main PIDE.session.global_options += main PIDE.session.commands_changed += main handle_phase(PIDE.session.phase) handle_update() } override def exit(): Unit = { PIDE.session.phase_changed -= main PIDE.session.global_options -= main PIDE.session.commands_changed -= main } }