clarified GUI.Selector, with support for separator as pseudo-entry;
clarified signature;
--- a/src/Pure/GUI/gui.scala Wed Nov 09 14:20:52 2022 +0100
+++ b/src/Pure/GUI/gui.scala Wed Nov 09 19:42:21 2022 +0100
@@ -13,7 +13,9 @@
import java.awt.geom.AffineTransform
import javax.swing.{ImageIcon, JButton, JDialog, JFrame, JLabel, JLayeredPane, JOptionPane,
JTextField, JWindow, LookAndFeel, UIManager, SwingUtilities}
-import scala.swing.{CheckBox, ComboBox, ScrollPane, TextArea}
+
+import scala.swing.{CheckBox, ComboBox, ScrollPane, TextArea, ListView, Label, Separator,
+ Orientation}
import scala.swing.event.{ButtonClicked, SelectionChanged}
@@ -127,9 +129,45 @@
reactions += { case ButtonClicked(_) => clicked(selected); clicked() }
}
- class Selector[A](val entries: List[A]) extends ComboBox[A](entries) {
+
+ /* list selector */
+
+ object Selector {
+ sealed abstract class Entry[A] {
+ def get_item: Option[A] =
+ this match {
+ case Item(item, _) => Some(item)
+ case _ => None
+ }
+ }
+ case class Item[A](item: A, description: String = "") extends Entry[A] {
+ override def toString: String = proper_string(description) getOrElse item.toString
+ }
+ case class Separator[A](name: String = "") extends Entry[A] {
+ override def toString: String = "<b>" + name + "</b>"
+ }
+
+ def item(name: String): Item[String] = Item(name)
+ def separator: Separator[String] = Separator()
+ }
+
+ class Selector[A](val entries: List[Selector.Entry[A]])
+ extends ComboBox[Selector.Entry[A]](entries) {
def changed(): Unit = {}
+ private val default_renderer = renderer
+ private val render_separator = new Separator
+ private val render_label = new Label
+ renderer =
+ (list: ListView[_ <: Selector.Entry[A]], selected: Boolean, focus: Boolean, entry: Selector.Entry[A], i: Int) => {
+ entry match {
+ case sep: Selector.Separator[_] =>
+ if (sep.name.isEmpty) render_separator
+ else { render_label.text = entry.toString; render_label }
+ case _ => default_renderer.componentFor(list, selected, focus, entry, i)
+ }
+ }
+
listenTo(selection)
reactions += { case SelectionChanged(_) => changed() }
}
@@ -141,8 +179,9 @@
class Zoom extends Selector[String](
List("50%", "70%", "85%", "100%", "125%", "150%", "175%", "200%", "300%", "400%")
+ .map(GUI.Selector.item)
) {
- def factor: Int = parse(selection.item)
+ def factor: Int = parse(selection.item.toString)
private def parse(text: String): Int =
text match {
@@ -161,7 +200,8 @@
}
}
- makeEditable()(c => new ComboBox.BuiltInEditor(c)(text => print(parse(text)), x => x))
+ makeEditable()(c =>
+ new ComboBox.BuiltInEditor(c)(text => Selector.Item(print(parse(text))), _.toString))
peer.getEditor.getEditorComponent match {
case text: JTextField => text.setColumns(4)
case _ =>
--- a/src/Pure/Thy/sessions.scala Wed Nov 09 14:20:52 2022 +0100
+++ b/src/Pure/Thy/sessions.scala Wed Nov 09 19:42:21 2022 +0100
@@ -507,6 +507,9 @@
def dirs: List[Path] = dir :: directories
+ def main_group: Boolean = groups.contains("main")
+ def doc_group: Boolean = groups.contains("doc")
+
def timeout_ignored: Boolean =
!options.bool("timeout_build") || Time.seconds(options.real("timeout")) < Time.ms(1)
--- a/src/Pure/Tools/spell_checker.scala Wed Nov 09 14:20:52 2022 +0100
+++ b/src/Pure/Tools/spell_checker.scala Wed Nov 09 19:42:21 2022 +0100
@@ -85,12 +85,14 @@
}
}
- def dictionaries: List[Dictionary] =
+ lazy val dictionaries: List[Dictionary] =
for {
path <- Path.split(Isabelle_System.getenv("JORTHO_DICTIONARIES"))
if path.is_file
} yield new Dictionary(path)
+ def get_dictionary(lang: String): Option[Dictionary] = dictionaries.find(_.lang == lang)
+
/* create spell checker */
@@ -260,7 +262,7 @@
if (options.bool("spell_checker")) {
val lang = options.string("spell_checker_dictionary")
if (current_spell_checker._1 != lang) {
- Spell_Checker.dictionaries.find(_.lang == lang) match {
+ Spell_Checker.get_dictionary(lang) match {
case Some(dictionary) =>
val spell_checker =
Exn.capture { Spell_Checker(dictionary) } match {
--- a/src/Tools/jEdit/src/document_dockable.scala Wed Nov 09 14:20:52 2022 +0100
+++ b/src/Tools/jEdit/src/document_dockable.scala Wed Nov 09 19:42:21 2022 +0100
@@ -187,10 +187,17 @@
/* controls */
- private val document_session: GUI.Selector[String] =
- new GUI.Selector(JEdit_Sessions.sessions_structure().build_topological_order.sorted) {
+ private val document_session: GUI.Selector[String] = {
+ val sessions = JEdit_Sessions.sessions_structure()
+ val all_sessions = sessions.build_topological_order.sorted
+ val doc_sessions = all_sessions.filter(name => sessions(name).doc_group)
+ new GUI.Selector(
+ doc_sessions.map(GUI.Selector.item) ::: List(GUI.Selector.separator) :::
+ all_sessions.map(GUI.Selector.item)
+ ) {
val title = "Session"
}
+ }
private val build_button =
new GUI.Button("<html><b>Build</b></html>") {
--- a/src/Tools/jEdit/src/jedit_sessions.scala Wed Nov 09 14:20:52 2022 +0100
+++ b/src/Tools/jEdit/src/jedit_sessions.scala Wed Nov 09 19:42:21 2022 +0100
@@ -69,35 +69,35 @@
/* logic selector */
- private sealed case class Logic_Entry(name: String = "", description: String = "") {
- override def toString: String = proper_string(description) getOrElse name
- }
-
def logic_selector(options: Options_Variable, autosave: Boolean = false): JEdit_Options.Entry = {
GUI_Thread.require {}
- val default_entry = Logic_Entry(description = "default (" + logic_name(options.value) + ")")
+ val default_entry =
+ GUI.Selector.Item("", description = "default (" + logic_name(options.value) + ")")
val session_entries = {
val sessions = sessions_structure(options = options.value)
- val (main_sessions, other_sessions) =
- sessions.imports_topological_order.partition(name => sessions(name).groups.contains("main"))
- (main_sessions.sorted ::: other_sessions.sorted).map(name => Logic_Entry(name = name))
+ val all_sessions = sessions.imports_topological_order
+ val main_sessions = all_sessions.filter(name => sessions(name).main_group)
+
+ main_sessions.map(GUI.Selector.item) ::: List(GUI.Selector.separator) :::
+ all_sessions.map(GUI.Selector.item)
}
- new GUI.Selector[Logic_Entry](default_entry :: session_entries)
- with JEdit_Options.Entry {
+ new GUI.Selector(default_entry :: session_entries) with JEdit_Options.Entry {
name = jedit_logic_option
tooltip = "Logic session name (change requires restart)"
val title = "Logic"
def load(): Unit = {
val logic = options.string(jedit_logic_option)
- entries.find(_.name == logic) match {
+ entries.find { case GUI.Selector.Item(item, _) => item == logic case _ => false } match {
case Some(entry) => selection.item = entry
case None =>
}
}
- def save(): Unit = options.string(jedit_logic_option) = selection.item.name
+ def save(): Unit =
+ for (item <- selection.item.get_item) options.string(jedit_logic_option) = item
+
override def changed(): Unit = if (autosave) save()
load()
--- a/src/Tools/jEdit/src/jedit_spell_checker.scala Wed Nov 09 14:20:52 2022 +0100
+++ b/src/Tools/jEdit/src/jedit_spell_checker.scala Wed Nov 09 19:42:21 2022 +0100
@@ -85,18 +85,19 @@
val option_name = "spell_checker_dictionary"
val opt = PIDE.options.value.check_name(option_name)
- new GUI.Selector[Spell_Checker.Dictionary](Spell_Checker.dictionaries) with JEdit_Options.Entry {
+ new GUI.Selector(Spell_Checker.dictionaries.map(GUI.Selector.Item(_))) with JEdit_Options.Entry {
name = option_name
tooltip = GUI.tooltip_lines(opt.print_default)
val title = opt.title()
def load(): Unit = {
val lang = PIDE.options.string(option_name)
- entries.find(_.lang == lang) match {
- case Some(entry) => selection.item = entry
+ Spell_Checker.get_dictionary(lang) match {
+ case Some(dict) => selection.item = GUI.Selector.Item(dict)
case None =>
}
}
- def save(): Unit = PIDE.options.string(option_name) = selection.item.lang
+ def save(): Unit =
+ for (item <- selection.item.get_item) PIDE.options.string(option_name) = item.lang
load()
}
--- a/src/Tools/jEdit/src/monitor_dockable.scala Wed Nov 09 14:20:52 2022 +0100
+++ b/src/Tools/jEdit/src/monitor_dockable.scala Wed Nov 09 19:42:21 2022 +0100
@@ -64,10 +64,11 @@
/* controls */
- private val select_data = new GUI.Selector[String](ML_Statistics.all_fields.map(_._1)) {
- tooltip = "Select visualized data collection"
- override def changed(): Unit = { data_name = selection.item; update_chart() }
- }
+ private val select_data =
+ new GUI.Selector(ML_Statistics.all_fields.map { case (a, _) => GUI.Selector.item(a) }) {
+ tooltip = "Select visualized data collection"
+ override def changed(): Unit = { data_name = selection.item.toString; update_chart() }
+ }
private val limit_data = new TextField("200", 5) {
tooltip = "Limit for accumulated data"