Mercurial > cgi-bin > hgweb.cgi > ClipMan
view src/name/blackcap/clipman/CoerceDialog.kt @ 57:c6cccbe2f393
Port to OpenJDK 15 (mostly done).
author | David Barts <n5jrn@me.com> |
---|---|
date | Wed, 23 Mar 2022 23:56:29 -0700 |
parents | 22725d4d7849 |
children | 88056f373a94 |
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 (!suitedForCoercing(selected)) { return } if (selected == null) { return /* redundant, but makes kotlinc happy */ } if (badSize(_pSize, PROP_SIZE, "proportionally-spaced") || badSize(_mSize, MONO_SIZE, "monospaced")) { return } 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) } 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 } } } /** * See if the selected pasteboard item is suitable for coercing. If not, * issue an error dialog. */ fun suitedForCoercing(selected: QueueItem?): Boolean { if (selected == null) { JOptionPane.showMessageDialog(Application.frame, "No item selected.", "Error", JOptionPane.ERROR_MESSAGE) return false } if (selected.contents is PasteboardItem.Plain) { JOptionPane.showMessageDialog(Application.frame, "Only styled texts may be coerced.", "Error", JOptionPane.ERROR_MESSAGE) return false } return true }