Mercurial > cgi-bin > hgweb.cgi > ClipMan
view src/name/blackcap/clipman/CoerceDialog.kt @ 47:19d9da731c43
Recoded; cleaned up root namespace, removed race conditions.
author | David Barts <n5jrn@me.com> |
---|---|
date | Sun, 12 Apr 2020 14:31:06 -0700 |
parents | 339e2da5bf83 |
children | 22725d4d7849 |
line wrap: on
line source
/* * 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.util.logging.Level import java.util.logging.Logger import javax.swing.* import javax.swing.event.DocumentEvent import javax.swing.event.DocumentListener class CoerceDialog: JDialog(Application.frame), ActionListener { private val FONTS = GraphicsEnvironment.getLocalGraphicsEnvironment().availableFontFamilyNames.copyOf().apply { sort() } private val SIZES = arrayOf(9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 16.0f, 18.0f, 24.0f, 36.0f, 48.0f, 64.0f, 72.0f, 96.0f, 144.0f, 288.0f) /* the proportional font family */ private val _pFamily = JComboBox<String>(FONTS).apply { selectedIndex = getFontIndex(Font.SERIF) 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 = PROP_SIZE.toFloat() 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 { selectedIndex = getFontIndex(Font.MONOSPACED) 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 = MONO_SIZE.toFloat() it.alignmentX = JComboBox.LEFT_ALIGNMENT it.setEditable(true) } val mSize: Float get() { return _mSize.selectedItem as Float } /* standard spacing between elements (10 pixels ≅ 1/7") and half that */ private val BW = 5 private val BW2 = 10 /* buttons */ private val _coerce = JButton("Coerce").also { it.actionCommand = "Coerce" it.addActionListener(this) } private val _cancel = JButton("Cancel").also { it.actionCommand = "Cancel" it.addActionListener(this) } /* initializer */ init { title = "Coerce Fonts" 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("Coerce proportionally-spaced text to…")) 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("Coerce monospaced text to…")) 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.X_AXIS).apply { alignmentX = Box.CENTER_ALIGNMENT border = BorderFactory.createEmptyBorder(BW, BW2, BW, BW2) add(Box.createGlue()) add(_cancel) add(Box.createGlue()) add(_coerce) add(Box.createGlue()) }) }) } rootPane.setDefaultButton(_coerce) pack() setResizable(false) } override fun actionPerformed(e: ActionEvent) { when (e.actionCommand) { "Coerce" -> { setVisible(false) coerce() } "Cancel" -> setVisible(false) } } private fun leftLabel(text: String) = JLabel(text).apply { alignmentX = JLabel.LEFT_ALIGNMENT } private fun coerce() { val selected = Application.queue.getSelected() if (selected == null) { JOptionPane.showMessageDialog(Application.frame, "No item selected.", "Error", JOptionPane.ERROR_MESSAGE) } else { val (plain, html) = when (selected.contents) { is PasteboardItem.Plain -> Pair(selected.contents.plain, null) is PasteboardItem.HTML -> Pair(selected.contents.plain, selected.contents.html) is PasteboardItem.RTF -> Pair(selected.contents.plain, selected.contents.html) } if (html == null) { JOptionPane.showMessageDialog(Application.frame, "Only styled texts may be coerced.", "Error", JOptionPane.ERROR_MESSAGE) } else { if (badSize(_pSize, PROP_SIZE, "proportionally-spaced") || badSize(_mSize, MONO_SIZE, "monospaced")) { return } PasteboardItem.write( PasteboardItem.HTML( plain, coerceHTML(html, normalizeFont(pFamily), pSize, normalizeFont(mFamily), mSize))) } } } private fun badSize(control: JComboBox<Float>, default: Int, fontType: String): Boolean { val size = control.selectedItem as? Float if (size == null || size < 1.0f) { JOptionPane.showMessageDialog(Application.frame, "Invalid ${fontType} font size.", "Error", JOptionPane.ERROR_MESSAGE) control.selectedItem = default.toFloat() return true } return false } private fun getFontIndex(font: String): Int { val found = FONTS.indexOf(font) if (found < 0) { LOGGER.log(Level.WARNING, "font '${font}' not found") return 0 } return found } private fun normalizeFont(font: String): String { val lcFont = font.toLowerCase() return when (lcFont) { in setOf("monospace", "serif", "sans-serif") -> lcFont "monospaced" -> "monospace" "sansserif" -> "sans-serif" else -> font } } }