comparison src/name/blackcap/clipman/SettingsDialog.kt @ 41:33fbe3a78d84

Got the settings stuff compiling (untested).
author David Barts <n5jrn@me.com>
date Sat, 08 Feb 2020 22:10:01 -0700
parents
children 339e2da5bf83
comparison
equal deleted inserted replaced
40:c803a2c89ea0 41:33fbe3a78d84
1 /*
2 * The dialog that controls font corecion.
3 */
4 package name.blackcap.clipman
5
6 import java.awt.Color
7 import java.awt.Container
8 import java.awt.Dimension
9 import java.awt.Font
10 import java.awt.GraphicsEnvironment
11 import java.awt.Toolkit
12 import java.awt.event.ActionEvent
13 import java.awt.event.ActionListener
14 import java.io.BufferedWriter
15 import java.io.FileOutputStream
16 import java.io.IOException
17 import java.io.OutputStreamWriter
18 import java.util.Hashtable
19 import java.util.Properties
20 import java.util.logging.Level
21 import java.util.logging.Logger
22 import javax.swing.*
23 import javax.swing.event.ChangeEvent
24 import javax.swing.event.ChangeListener
25 import kotlin.math.log10
26 import kotlin.math.pow
27 import kotlin.math.roundToInt
28 import kotlin.text.toFloat
29 import kotlin.text.toInt
30
31 /* work around name shadowing */
32 private val _PROPS = PROPERTIES
33
34 class SettingsDialog: JDialog(frame.v), ActionListener, ChangeListener {
35 /* the proportional font family */
36 private val _pFamily = JComboBox<String>(FONTS).apply {
37 selectedItem = _PROPS.getString("prop.family")
38 alignmentX = JComboBox.LEFT_ALIGNMENT
39 }
40 val pFamily: String
41 get() {
42 return _pFamily.selectedItem as String
43 }
44
45 /* the proportional font size */
46 private val _pSize = JComboBox<Float>(SIZES).also {
47 it.selectedItem = _PROPS.getFloat("prop.size")
48 it.alignmentX = JComboBox.LEFT_ALIGNMENT
49 it.setEditable(true)
50 }
51 val pSize: Float
52 get() {
53 return _pSize.selectedItem as Float
54 }
55
56 /* the monospaced font family */
57 private val _mFamily = JComboBox<String>(FONTS).apply {
58 selectedItem = _PROPS.getString("mono.family")
59 alignmentX = JComboBox.LEFT_ALIGNMENT
60 }
61 val mFamily: String
62 get() {
63 return _mFamily.selectedItem as String
64 }
65
66 /* the monospaced font size */
67 private val _mSize = JComboBox<Float>(SIZES).also {
68 it.selectedItem = _PROPS.getFloat("mono.size")
69 it.alignmentX = JComboBox.LEFT_ALIGNMENT
70 it.setEditable(true)
71 }
72 val mSize: Float
73 get() {
74 return _mSize.selectedItem as Float
75 }
76
77 /* max queue length */
78 private val _qLength = _PROPS.getInt("queue.length")
79 private val _qlSlider = JSlider(10000, 30000, spinToSlide(_qLength)).also {
80 it.majorTickSpacing = 10000
81 it.paintTicks = true
82 it.labelTable = Hashtable<Int, String>().apply {
83 put(10000, "10")
84 put(20000, "100")
85 put(30000, "1000")
86 }
87 it.addChangeListener(this)
88 }
89 private val _qlSpinner = JSpinner(SpinnerNumberModel(_qLength, 10, 1000, 1)).also {
90 it.addChangeListener(this)
91 }
92 val qLength: Int
93 get() {
94 return _qlSpinner.value as Int
95 }
96
97 /* standard spacing between elements (10 pixels ≅ 1/7") and half that */
98 private val BW = 5
99 private val BW2 = 10
100
101 /* buttons */
102 private val _ok = JButton("OK").also {
103 it.actionCommand = "OK"
104 it.addActionListener(this)
105 }
106
107 private val _cancel = JButton("Cancel").also {
108 it.actionCommand = "Cancel"
109 it.addActionListener(this)
110 }
111
112 private val _rad = JButton("Restore All Defaults").also {
113 it.actionCommand = "Restore"
114 it.addActionListener(this)
115 }
116
117 /* initializer */
118 init {
119 title = "Preferences"
120 contentPane.apply {
121 add(Box(BoxLayout.Y_AXIS).apply {
122 add(Box(BoxLayout.Y_AXIS).apply {
123 border = BorderFactory.createEmptyBorder(BW2, BW2, BW, BW2)
124 alignmentX = Box.CENTER_ALIGNMENT
125 add(leftLabel("Default proportionally-spaced font:"))
126 add(Box.createVerticalStrut(BW))
127 add(Box(BoxLayout.X_AXIS).apply {
128 alignmentX = Box.LEFT_ALIGNMENT
129 add(Box.createGlue())
130 add(Box(BoxLayout.Y_AXIS).apply {
131 add(leftLabel("Family:"))
132 add(_pFamily)
133 })
134 add(Box.createGlue())
135 add(Box(BoxLayout.Y_AXIS).apply {
136 add(leftLabel("Size:"))
137 add(_pSize)
138 })
139 add(Box.createGlue())
140 })
141 })
142 add(JSeparator())
143 add(Box(BoxLayout.Y_AXIS).apply {
144 alignmentX = Box.CENTER_ALIGNMENT
145 border = BorderFactory.createEmptyBorder(BW, BW2, BW, BW2)
146 add(leftLabel("Default monospaced font:"))
147 add(Box.createVerticalStrut(BW))
148 add(Box(BoxLayout.X_AXIS).apply {
149 alignmentX = Box.LEFT_ALIGNMENT
150 add(Box.createGlue())
151 add(Box(BoxLayout.Y_AXIS).apply {
152 add(leftLabel("Family:"))
153 add(_mFamily)
154 })
155 add(Box.createGlue())
156 add(Box(BoxLayout.Y_AXIS).apply {
157 add(leftLabel("Size:"))
158 add(_mSize)
159 })
160 add(Box.createGlue())
161 })
162 })
163 add(JSeparator())
164 add(Box(BoxLayout.Y_AXIS).apply {
165 alignmentX = Box.CENTER_ALIGNMENT
166 border = BorderFactory.createEmptyBorder(BW, BW2, BW, BW2)
167 add(leftLabel("Maximum queue size:"))
168 add(Box.createVerticalStrut(BW))
169 add(Box(BoxLayout.X_AXIS).apply {
170 alignmentX = Box.LEFT_ALIGNMENT
171 add(Box.createGlue())
172 add(_qlSlider)
173 add(Box.createGlue())
174 add(_qlSpinner)
175 add(Box.createGlue())
176 })
177 })
178 add(JSeparator())
179 add(Box(BoxLayout.X_AXIS).apply {
180 alignmentX = Box.CENTER_ALIGNMENT
181 border = BorderFactory.createEmptyBorder(BW, BW2, BW, BW2)
182 add(Box.createGlue())
183 add(_rad)
184 add(Box.createGlue())
185 add(_cancel)
186 add(Box.createGlue())
187 add(_ok)
188 add(Box.createGlue())
189 })
190 })
191 }
192 rootPane.setDefaultButton(_ok)
193 pack()
194 setResizable(false)
195 }
196
197 override fun actionPerformed(e: ActionEvent) {
198 when (e.actionCommand) {
199 "OK" -> {
200 writeProperties()
201 queue.v.maxSize = qLength
202 setVisible(false)
203 }
204 "Cancel" -> setVisible(false)
205 "Restore" -> revertProperties()
206 }
207 }
208
209 override fun stateChanged(e: ChangeEvent) {
210 when (val source = e.source) {
211 source === _qlSlider ->
212 _qlSpinner.value = (10.0).pow(_qlSlider.value.toDouble() / 10000.0).roundToInt()
213 source === _qlSpinner ->
214 _qlSlider.value = spinToSlide(_qlSpinner.value as Int)
215 }
216 }
217
218 private fun spinToSlide(value: Int): Int =
219 (log10(value.toDouble()) * 10000.0).roundToInt()
220
221 private fun leftLabel(text: String) = JLabel(text).apply {
222 alignmentX = JLabel.LEFT_ALIGNMENT
223 }
224
225 private fun badSize(control: JComboBox<Float>, default: Float, fontType: String): Boolean {
226 val size = control.selectedItem as? Float
227 if (size == null || size < 1.0f) {
228 JOptionPane.showMessageDialog(frame.v,
229 "Invalid ${fontType} font size.",
230 "Error",
231 JOptionPane.ERROR_MESSAGE)
232 control.selectedItem = default
233 return true
234 }
235 return false
236 }
237
238 private fun revertProperties()
239 {
240 val params = arrayOf("mono.family", "mono.size", "prop.family", "prop.size", "queue.length")
241 for (param in params) {
242 _PROPS.put(param, DPROPERTIES.get(param))
243 }
244 _mFamily.selectedItem = _PROPS.getString("mono.family")
245 _mSize.selectedItem = _PROPS.getFloat("mono.size")
246 _pFamily.selectedItem = _PROPS.getString("prop.family")
247 _pSize.selectedItem = _PROPS.getFloat("prop.size")
248 val ql = _PROPS.getInt("queue.length")
249 _qlSpinner.value = ql
250 _qlSlider.value = spinToSlide(ql)
251 }
252
253 private fun writeProperties()
254 {
255 try {
256 BufferedWriter(OutputStreamWriter(FileOutputStream(PROP_FILE), CHARSET)).use {
257 _PROPS.put("mono.family", mFamily)
258 _PROPS.put("mono.size", mSize.toString())
259 _PROPS.put("prop.family", pFamily)
260 _PROPS.put("prop.size", pSize.toString())
261 _PROPS.put("queue.length", qLength.toString())
262 _PROPS.store(it, null)
263 }
264 } catch (e: IOException) {
265 LOGGER.log(Level.WARNING, "IOException writing properties file")
266 val message = e.message
267 if (message != null && !message.isEmpty()) {
268 LOGGER.log(Level.WARNING, message)
269 }
270 JOptionPane.showMessageDialog(frame.v,
271 "Unable to write settings.",
272 "Error",
273 JOptionPane.ERROR_MESSAGE)
274 }
275 }
276 }
277
278 val settingsDialog = SettingsDialog()
279
280 fun Properties.getString(key: String): String = get(key) as String
281
282 fun Properties.getInt(key: String): Int = getString(key).toInt()
283
284 fun Properties.getFloat(key: String): Float = getString(key).toFloat()