Mercurial > cgi-bin > hgweb.cgi > ClipMan
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/name/blackcap/clipman/SettingsDialog.kt Sat Feb 08 22:10:01 2020 -0700 @@ -0,0 +1,284 @@ +/* + * The dialog that controls font corecion. + */ +package name.blackcap.clipman + +import java.awt.Color +import java.awt.Container +import java.awt.Dimension +import java.awt.Font +import java.awt.GraphicsEnvironment +import java.awt.Toolkit +import java.awt.event.ActionEvent +import java.awt.event.ActionListener +import java.io.BufferedWriter +import java.io.FileOutputStream +import java.io.IOException +import java.io.OutputStreamWriter +import java.util.Hashtable +import java.util.Properties +import java.util.logging.Level +import java.util.logging.Logger +import javax.swing.* +import javax.swing.event.ChangeEvent +import javax.swing.event.ChangeListener +import kotlin.math.log10 +import kotlin.math.pow +import kotlin.math.roundToInt +import kotlin.text.toFloat +import kotlin.text.toInt + +/* work around name shadowing */ +private val _PROPS = PROPERTIES + +class SettingsDialog: JDialog(frame.v), ActionListener, ChangeListener { + /* the proportional font family */ + private val _pFamily = JComboBox<String>(FONTS).apply { + selectedItem = _PROPS.getString("prop.family") + alignmentX = JComboBox.LEFT_ALIGNMENT + } + val pFamily: String + get() { + return _pFamily.selectedItem as String + } + + /* the proportional font size */ + private val _pSize = JComboBox<Float>(SIZES).also { + it.selectedItem = _PROPS.getFloat("prop.size") + it.alignmentX = JComboBox.LEFT_ALIGNMENT + it.setEditable(true) + } + val pSize: Float + get() { + return _pSize.selectedItem as Float + } + + /* the monospaced font family */ + private val _mFamily = JComboBox<String>(FONTS).apply { + selectedItem = _PROPS.getString("mono.family") + alignmentX = JComboBox.LEFT_ALIGNMENT + } + val mFamily: String + get() { + return _mFamily.selectedItem as String + } + + /* the monospaced font size */ + private val _mSize = JComboBox<Float>(SIZES).also { + it.selectedItem = _PROPS.getFloat("mono.size") + it.alignmentX = JComboBox.LEFT_ALIGNMENT + it.setEditable(true) + } + val mSize: Float + get() { + return _mSize.selectedItem as Float + } + + /* max queue length */ + private val _qLength = _PROPS.getInt("queue.length") + private val _qlSlider = JSlider(10000, 30000, spinToSlide(_qLength)).also { + it.majorTickSpacing = 10000 + it.paintTicks = true + it.labelTable = Hashtable<Int, String>().apply { + put(10000, "10") + put(20000, "100") + put(30000, "1000") + } + it.addChangeListener(this) + } + private val _qlSpinner = JSpinner(SpinnerNumberModel(_qLength, 10, 1000, 1)).also { + it.addChangeListener(this) + } + val qLength: Int + get() { + return _qlSpinner.value as Int + } + + /* standard spacing between elements (10 pixels ≅ 1/7") and half that */ + private val BW = 5 + private val BW2 = 10 + + /* buttons */ + private val _ok = JButton("OK").also { + it.actionCommand = "OK" + it.addActionListener(this) + } + + private val _cancel = JButton("Cancel").also { + it.actionCommand = "Cancel" + it.addActionListener(this) + } + + private val _rad = JButton("Restore All Defaults").also { + it.actionCommand = "Restore" + it.addActionListener(this) + } + + /* initializer */ + init { + title = "Preferences" + contentPane.apply { + add(Box(BoxLayout.Y_AXIS).apply { + add(Box(BoxLayout.Y_AXIS).apply { + border = BorderFactory.createEmptyBorder(BW2, BW2, BW, BW2) + alignmentX = Box.CENTER_ALIGNMENT + add(leftLabel("Default proportionally-spaced font:")) + add(Box.createVerticalStrut(BW)) + add(Box(BoxLayout.X_AXIS).apply { + alignmentX = Box.LEFT_ALIGNMENT + add(Box.createGlue()) + add(Box(BoxLayout.Y_AXIS).apply { + add(leftLabel("Family:")) + add(_pFamily) + }) + add(Box.createGlue()) + add(Box(BoxLayout.Y_AXIS).apply { + add(leftLabel("Size:")) + add(_pSize) + }) + add(Box.createGlue()) + }) + }) + add(JSeparator()) + add(Box(BoxLayout.Y_AXIS).apply { + alignmentX = Box.CENTER_ALIGNMENT + border = BorderFactory.createEmptyBorder(BW, BW2, BW, BW2) + add(leftLabel("Default monospaced font:")) + add(Box.createVerticalStrut(BW)) + add(Box(BoxLayout.X_AXIS).apply { + alignmentX = Box.LEFT_ALIGNMENT + add(Box.createGlue()) + add(Box(BoxLayout.Y_AXIS).apply { + add(leftLabel("Family:")) + add(_mFamily) + }) + add(Box.createGlue()) + add(Box(BoxLayout.Y_AXIS).apply { + add(leftLabel("Size:")) + add(_mSize) + }) + add(Box.createGlue()) + }) + }) + add(JSeparator()) + add(Box(BoxLayout.Y_AXIS).apply { + alignmentX = Box.CENTER_ALIGNMENT + border = BorderFactory.createEmptyBorder(BW, BW2, BW, BW2) + add(leftLabel("Maximum queue size:")) + add(Box.createVerticalStrut(BW)) + add(Box(BoxLayout.X_AXIS).apply { + alignmentX = Box.LEFT_ALIGNMENT + add(Box.createGlue()) + add(_qlSlider) + add(Box.createGlue()) + add(_qlSpinner) + add(Box.createGlue()) + }) + }) + add(JSeparator()) + add(Box(BoxLayout.X_AXIS).apply { + alignmentX = Box.CENTER_ALIGNMENT + border = BorderFactory.createEmptyBorder(BW, BW2, BW, BW2) + add(Box.createGlue()) + add(_rad) + add(Box.createGlue()) + add(_cancel) + add(Box.createGlue()) + add(_ok) + add(Box.createGlue()) + }) + }) + } + rootPane.setDefaultButton(_ok) + pack() + setResizable(false) + } + + override fun actionPerformed(e: ActionEvent) { + when (e.actionCommand) { + "OK" -> { + writeProperties() + queue.v.maxSize = qLength + setVisible(false) + } + "Cancel" -> setVisible(false) + "Restore" -> revertProperties() + } + } + + override fun stateChanged(e: ChangeEvent) { + when (val source = e.source) { + source === _qlSlider -> + _qlSpinner.value = (10.0).pow(_qlSlider.value.toDouble() / 10000.0).roundToInt() + source === _qlSpinner -> + _qlSlider.value = spinToSlide(_qlSpinner.value as Int) + } + } + + private fun spinToSlide(value: Int): Int = + (log10(value.toDouble()) * 10000.0).roundToInt() + + private fun leftLabel(text: String) = JLabel(text).apply { + alignmentX = JLabel.LEFT_ALIGNMENT + } + + private fun badSize(control: JComboBox<Float>, default: Float, fontType: String): Boolean { + val size = control.selectedItem as? Float + if (size == null || size < 1.0f) { + JOptionPane.showMessageDialog(frame.v, + "Invalid ${fontType} font size.", + "Error", + JOptionPane.ERROR_MESSAGE) + control.selectedItem = default + return true + } + return false + } + + private fun revertProperties() + { + val params = arrayOf("mono.family", "mono.size", "prop.family", "prop.size", "queue.length") + for (param in params) { + _PROPS.put(param, DPROPERTIES.get(param)) + } + _mFamily.selectedItem = _PROPS.getString("mono.family") + _mSize.selectedItem = _PROPS.getFloat("mono.size") + _pFamily.selectedItem = _PROPS.getString("prop.family") + _pSize.selectedItem = _PROPS.getFloat("prop.size") + val ql = _PROPS.getInt("queue.length") + _qlSpinner.value = ql + _qlSlider.value = spinToSlide(ql) + } + + private fun writeProperties() + { + try { + BufferedWriter(OutputStreamWriter(FileOutputStream(PROP_FILE), CHARSET)).use { + _PROPS.put("mono.family", mFamily) + _PROPS.put("mono.size", mSize.toString()) + _PROPS.put("prop.family", pFamily) + _PROPS.put("prop.size", pSize.toString()) + _PROPS.put("queue.length", qLength.toString()) + _PROPS.store(it, null) + } + } catch (e: IOException) { + LOGGER.log(Level.WARNING, "IOException writing properties file") + val message = e.message + if (message != null && !message.isEmpty()) { + LOGGER.log(Level.WARNING, message) + } + JOptionPane.showMessageDialog(frame.v, + "Unable to write settings.", + "Error", + JOptionPane.ERROR_MESSAGE) + } + } +} + +val settingsDialog = SettingsDialog() + +fun Properties.getString(key: String): String = get(key) as String + +fun Properties.getInt(key: String): Int = getString(key).toInt() + +fun Properties.getFloat(key: String): Float = getString(key).toFloat()