| author | wenzelm |
| Tue, 06 Dec 2022 14:41:13 +0100 | |
| changeset 76577 | c662a56e77a8 |
| parent 76392 | 3fa81de0b6c5 |
| child 76578 | 06b001094ddb |
| permissions | -rw-r--r-- |
|
49245
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
wenzelm
parents:
diff
changeset
|
1 |
/* Title: Tools/jEdit/src/jedit_options.scala |
|
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
wenzelm
parents:
diff
changeset
|
2 |
Author: Makarius |
|
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
wenzelm
parents:
diff
changeset
|
3 |
|
|
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
wenzelm
parents:
diff
changeset
|
4 |
Options for Isabelle/jEdit. |
|
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
wenzelm
parents:
diff
changeset
|
5 |
*/ |
|
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
wenzelm
parents:
diff
changeset
|
6 |
|
|
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
wenzelm
parents:
diff
changeset
|
7 |
package isabelle.jedit |
|
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
wenzelm
parents:
diff
changeset
|
8 |
|
|
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
wenzelm
parents:
diff
changeset
|
9 |
|
|
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
wenzelm
parents:
diff
changeset
|
10 |
import isabelle._ |
|
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
wenzelm
parents:
diff
changeset
|
11 |
|
|
61607
a99125aa964f
prefer static Font -- evade spontaneous change of TextField.font seen with Metal L&F in Plugin Options / Isabelle / General / Apply;
wenzelm
parents:
60844
diff
changeset
|
12 |
import java.awt.{Font, Color}
|
|
49252
9e10481dd3c4
prefer global default font over IsabelleText of jEdit TextArea;
wenzelm
parents:
49248
diff
changeset
|
13 |
import javax.swing.{InputVerifier, JComponent, UIManager}
|
| 49246 | 14 |
import javax.swing.text.JTextComponent |
|
49252
9e10481dd3c4
prefer global default font over IsabelleText of jEdit TextArea;
wenzelm
parents:
49248
diff
changeset
|
15 |
|
| 49246 | 16 |
import scala.swing.{Component, CheckBox, TextArea}
|
17 |
||
| 49296 | 18 |
import org.gjt.sp.jedit.gui.ColorWellButton |
| 76390 | 19 |
import org.gjt.sp.jedit.{jEdit, AbstractOptionPane}
|
| 49296 | 20 |
|
| 49246 | 21 |
|
| 75393 | 22 |
object JEdit_Options {
|
| 75855 | 23 |
/* typed access and GUI components */ |
| 75849 | 24 |
|
| 75847 | 25 |
class Access[A](access: Options.Access_Variable[A], val name: String) {
|
26 |
def apply(): A = access.apply(name) |
|
27 |
def update(x: A): Unit = change(_ => x) |
|
28 |
def change(f: A => A): Unit = {
|
|
29 |
val x0 = apply() |
|
30 |
access.change(name, f) |
|
31 |
val x1 = apply() |
|
32 |
if (x0 != x1) changed() |
|
33 |
} |
|
34 |
def changed(): Unit = GUI_Thread.require { PIDE.session.update_options(access.options.value) }
|
|
35 |
} |
|
| 75848 | 36 |
|
37 |
class Bool_Access(name: String) extends Access(PIDE.options.bool, name) {
|
|
38 |
def set(): Unit = update(true) |
|
39 |
def reset(): Unit = update(false) |
|
40 |
def toggle(): Unit = change(b => !b) |
|
41 |
} |
|
| 75849 | 42 |
|
| 75852 | 43 |
class Bool_GUI(access: Bool_Access, label: String) |
| 75854 | 44 |
extends GUI.Check(label, init = access()) {
|
| 75851 | 45 |
def load(): Unit = { selected = access() }
|
| 75852 | 46 |
override def clicked(state: Boolean): Unit = access.update(state) |
| 75851 | 47 |
} |
48 |
||
49 |
||
| 75849 | 50 |
/* specific options */ |
51 |
||
52 |
object continuous_checking extends Bool_Access("editor_continuous_checking") {
|
|
53 |
override def changed(): Unit = {
|
|
54 |
super.changed() |
|
55 |
PIDE.plugin.deps_changed() |
|
56 |
} |
|
57 |
||
| 75852 | 58 |
class GUI extends Bool_GUI(this, "Continuous checking") {
|
59 |
tooltip = "Continuous checking of proof document (visible and required parts)" |
|
60 |
} |
|
| 75849 | 61 |
} |
62 |
||
63 |
object output_state extends Bool_Access("editor_output_state") {
|
|
64 |
override def changed(): Unit = GUI_Thread.require {
|
|
65 |
super.changed() |
|
66 |
PIDE.editor.flush_edits(hidden = true) |
|
67 |
PIDE.editor.flush() |
|
68 |
} |
|
69 |
||
| 75852 | 70 |
class GUI extends Bool_GUI(this, "Proof state") {
|
71 |
tooltip = "Output of proof state (normally shown on State panel)" |
|
72 |
} |
|
| 75849 | 73 |
} |
| 76390 | 74 |
|
75 |
||
76 |
/* editor pane for plugin options */ |
|
77 |
||
| 76391 | 78 |
trait Entry extends Component {
|
79 |
val title: String |
|
80 |
def load(): Unit |
|
81 |
def save(): Unit |
|
82 |
} |
|
83 |
||
| 76390 | 84 |
abstract class Isabelle_Options(name: String) extends AbstractOptionPane(name) {
|
| 76391 | 85 |
protected val components: List[(String, List[Entry])] |
| 76390 | 86 |
|
87 |
override def _init(): Unit = {
|
|
88 |
val dummy_property = "options.isabelle.dummy" |
|
89 |
||
90 |
for ((s, cs) <- components) {
|
|
91 |
if (s.nonEmpty) {
|
|
92 |
jEdit.setProperty(dummy_property, s) |
|
93 |
addSeparator(dummy_property) |
|
94 |
jEdit.setProperty(dummy_property, null) |
|
95 |
} |
|
96 |
for (c <- cs) addComponent(c.title, c.peer) |
|
97 |
} |
|
98 |
} |
|
99 |
||
100 |
override def _save(): Unit = {
|
|
101 |
for ((_, cs) <- components; c <- cs) c.save() |
|
102 |
} |
|
103 |
} |
|
104 |
||
105 |
class Isabelle_General_Options extends Isabelle_Options("isabelle-general") {
|
|
106 |
val options: JEdit_Options = PIDE.options |
|
107 |
||
108 |
private val predefined = |
|
109 |
List(JEdit_Sessions.logic_selector(options), |
|
110 |
JEdit_Spell_Checker.dictionaries_selector()) |
|
111 |
||
| 76391 | 112 |
protected val components: List[(String, List[Entry])] = |
| 76390 | 113 |
options.make_components(predefined, |
114 |
(for ((name, opt) <- options.value.opt_iterator if opt.public) yield name).toSet) |
|
115 |
} |
|
116 |
||
117 |
class Isabelle_Rendering_Options extends Isabelle_Options("isabelle-rendering") {
|
|
118 |
private val predefined = |
|
119 |
(for {
|
|
120 |
(name, opt) <- PIDE.options.value.opt_iterator |
|
| 76392 | 121 |
if name.endsWith("_color") && opt.section == "Rendering of Document Content"
|
| 76390 | 122 |
} yield PIDE.options.make_color_component(opt)).toList |
123 |
||
124 |
assert(predefined.nonEmpty) |
|
125 |
||
| 76391 | 126 |
protected val components: List[(String, List[Entry])] = |
| 76390 | 127 |
PIDE.options.make_components(predefined, _ => false) |
128 |
} |
|
|
52065
78f2475aa126
explicit notion of public options, which are shown in the editor options dialog;
wenzelm
parents:
51616
diff
changeset
|
129 |
} |
|
78f2475aa126
explicit notion of public options, which are shown in the editor options dialog;
wenzelm
parents:
51616
diff
changeset
|
130 |
|
| 75393 | 131 |
class JEdit_Options(init_options: Options) extends Options_Variable(init_options) {
|
| 49356 | 132 |
def color_value(s: String): Color = Color_Value(string(s)) |
133 |
||
| 76391 | 134 |
def make_color_component(opt: Options.Opt): JEdit_Options.Entry = {
|
|
57612
990ffb84489b
clarified module name: facilitate alternative GUI frameworks;
wenzelm
parents:
56752
diff
changeset
|
135 |
GUI_Thread.require {}
|
| 49296 | 136 |
|
137 |
val opt_name = opt.name |
|
138 |
val opt_title = opt.title("jedit")
|
|
139 |
||
140 |
val button = new ColorWellButton(Color_Value(opt.value)) |
|
| 76391 | 141 |
val component = |
142 |
new Component with JEdit_Options.Entry {
|
|
143 |
override lazy val peer: JComponent = button |
|
144 |
name = opt_name |
|
145 |
val title: String = opt_title |
|
146 |
def load(): Unit = button.setSelectedColor(Color_Value(string(opt_name))) |
|
147 |
def save(): Unit = string(opt_name) = Color_Value.print(button.getSelectedColor) |
|
148 |
} |
|
|
56622
891d1b8b64fb
clarified tooltip_lines: HTML.encode already takes care of newline (but not space);
wenzelm
parents:
56611
diff
changeset
|
149 |
component.tooltip = GUI.tooltip_lines(opt.print_default) |
| 49296 | 150 |
component |
151 |
} |
|
152 |
||
| 76391 | 153 |
def make_component(opt: Options.Opt): JEdit_Options.Entry = {
|
|
57612
990ffb84489b
clarified module name: facilitate alternative GUI frameworks;
wenzelm
parents:
56752
diff
changeset
|
154 |
GUI_Thread.require {}
|
| 49246 | 155 |
|
| 49270 | 156 |
val opt_name = opt.name |
157 |
val opt_title = opt.title("jedit")
|
|
| 49246 | 158 |
|
159 |
val component = |
|
160 |
if (opt.typ == Options.Bool) |
|
| 76391 | 161 |
new CheckBox with JEdit_Options.Entry {
|
| 49270 | 162 |
name = opt_name |
| 75827 | 163 |
val title: String = opt_title |
| 73337 | 164 |
def load(): Unit = selected = bool(opt_name) |
165 |
def save(): Unit = bool(opt_name) = selected |
|
| 49246 | 166 |
} |
167 |
else {
|
|
|
61742
fd3b214b0979
clarified font: GUI defaults might change dynamically;
wenzelm
parents:
61607
diff
changeset
|
168 |
val default_font = GUI.copy_font(UIManager.getFont("TextField.font"))
|
| 49246 | 169 |
val text_area = |
| 76391 | 170 |
new TextArea with JEdit_Options.Entry {
|
|
61742
fd3b214b0979
clarified font: GUI defaults might change dynamically;
wenzelm
parents:
61607
diff
changeset
|
171 |
if (default_font != null) font = default_font |
| 49270 | 172 |
name = opt_name |
| 75827 | 173 |
val title: String = opt_title |
| 73337 | 174 |
def load(): Unit = text = value.check_name(opt_name).value |
175 |
def save(): Unit = |
|
|
65236
4fa82bbb394e
afford early initialization of JEdit_Options, but it may lead to messy exception trace for malformed etc/preferences (see also 6eeaaefcea56);
wenzelm
parents:
62227
diff
changeset
|
176 |
try { JEdit_Options.this += (opt_name, text) }
|
| 49317 | 177 |
catch {
|
178 |
case ERROR(msg) => |
|
| 51616 | 179 |
GUI.error_dialog(this.peer, "Failed to update options", |
180 |
GUI.scrollable_text(msg)) |
|
| 49317 | 181 |
} |
| 49246 | 182 |
} |
| 75827 | 183 |
text_area.peer.setInputVerifier({
|
184 |
case text: JTextComponent => |
|
185 |
try { value + (opt_name, text.getText); true }
|
|
186 |
catch { case ERROR(_) => false }
|
|
187 |
case _ => true |
|
| 49246 | 188 |
}) |
|
56752
72b4205f4de9
uniform focus traversal via TAB / Shift-TAB for all fields, in contrast to Java defaults, but in accordance to occasional jEdit practice;
wenzelm
parents:
56662
diff
changeset
|
189 |
GUI.plain_focus_traversal(text_area.peer) |
| 49246 | 190 |
text_area |
191 |
} |
|
| 49247 | 192 |
component.load() |
|
56622
891d1b8b64fb
clarified tooltip_lines: HTML.encode already takes care of newline (but not space);
wenzelm
parents:
56611
diff
changeset
|
193 |
component.tooltip = GUI.tooltip_lines(opt.print_default) |
| 49246 | 194 |
component |
195 |
} |
|
| 49270 | 196 |
|
| 75393 | 197 |
def make_components( |
| 76391 | 198 |
predefined: List[JEdit_Options.Entry], |
| 75393 | 199 |
filter: String => Boolean |
| 76391 | 200 |
) : List[(String, List[JEdit_Options.Entry])] = {
|
201 |
def mk_component(opt: Options.Opt): List[JEdit_Options.Entry] = |
|
| 49270 | 202 |
predefined.find(opt.name == _.name) match {
|
203 |
case Some(c) => List(c) |
|
204 |
case None => if (filter(opt.name)) List(make_component(opt)) else Nil |
|
205 |
} |
|
206 |
value.sections.sortBy(_._1).map( |
|
| 71601 | 207 |
{ case (a, opts) => (a, opts.sortBy(_.title("jedit")).flatMap(mk_component)) })
|
| 49270 | 208 |
.filterNot(_._2.isEmpty) |
209 |
} |
|
|
49245
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
wenzelm
parents:
diff
changeset
|
210 |
} |