Mercurial > cgi-bin > hgweb.cgi > ImagePrep
view src/name/blackcap/imageprep/Menus.kt @ 28:c310ec097194
Add Linux support.
author | David Barts <n5jrn@me.com> |
---|---|
date | Fri, 25 Dec 2020 19:07:47 -0800 |
parents | 92afaa27f40a |
children | 098c4f5507c7 |
line wrap: on
line source
/* * Menus. */ package name.blackcap.imageprep import java.awt.Graphics2D import java.awt.RenderingHints import java.awt.Toolkit import java.awt.Window import java.awt.event.ActionEvent import java.awt.event.ActionListener import java.awt.event.KeyEvent import java.awt.image.BufferedImage import java.io.File import java.io.IOException import java.util.logging.Level import java.util.logging.Logger import javax.imageio.IIOImage import javax.imageio.ImageIO import javax.imageio.ImageWriteParam import javax.imageio.ImageWriter import javax.imageio.stream.ImageOutputStream import javax.swing.* import javax.swing.filechooser.FileNameExtensionFilter /** * Our menu bar. What we display depends somewhat on the system type, as * the Mac gives us a gratuitous menu bar entry for handling some stuff. */ class MyMenuBar: JMenuBar() { private var currentInputDirectory = File(System.getProperty("user.dir")) private var currentOutputDirectory = File(Application.settingsDialog.outputTo) init { add(JMenu("File").apply { add(JMenuItem("Open & Scale…").apply { addActionListener(ActionListener { doOpen() }) makeShortcut(KeyEvent.VK_O) }) add(JMenuItem("Discard").apply { addActionListener(ActionListener { doDiscard() }) }) add(JMenuItem("Save & Close…").apply { addActionListener(ActionListener { doClose() }) makeShortcut(KeyEvent.VK_S) }) if (OS.type != OS.MAC) { add(JMenuItem("Preferences…").apply { addActionListener(ActionListener { Application.settingsDialog.setVisible(true) }) makeShortcut(KeyEvent.VK_COMMA) }) add(JMenuItem("Quit").apply { addActionListener(ActionListener { LOGGER.log(Level.INFO, "execution complete") System.exit(0) }) makeShortcut(KeyEvent.VK_Q) }) } }) add(JMenu("Help").apply { if (OS.type != OS.MAC) { add(JMenuItem("About ${Application.MYNAME}…").apply { addActionListener(ActionListener { showAboutDialog() }) }) } add(JMenuItem("${Application.MYNAME} Help…").apply { addActionListener(ActionListener { Application.helpDialog.setVisible(true) }) }) }) } fun getMenu(name: String): JMenu? { subElements.forEach { val jmenu = it.component as? JMenu if (jmenu?.text == name) { return jmenu } } return null } private fun doOpen() { val maxDim = MaxDimSpinner(Application.settingsDialog.maxDimension).apply { alignmentX = LEFT_ALIGNMENT } val acc = JPanel().apply { layout = BoxLayout(this, BoxLayout.Y_AXIS) add(Box.createGlue()) add(JLabel("Max. dim.:").apply { alignmentX = LEFT_ALIGNMENT }) add(maxDim) } val chooser = JFileChooser().apply { accessory = acc currentDirectory = currentInputDirectory fileFilter = FileNameExtensionFilter("Image Files", *ImageIO.getReaderFileSuffixes()) } if (chooser.showOpenDialog(Application.mainFrame) == JFileChooser.APPROVE_OPTION) { currentInputDirectory = chooser.selectedFile.canonicalFile.parentFile RotateDialog.makeDialog(chooser.selectedFile, maxDim.value as Int) } } private fun doDiscard() { val w = FocusManager.getCurrentManager().activeWindow as? RotateDialog if (w == null) { Toolkit.getDefaultToolkit().beep() return } w.close() } /* xxx - ImageIO bug? */ private class NullOutputStream : java.io.OutputStream() { override fun write(b: Int): Unit {} } private fun doClose() { val w = FocusManager.getCurrentManager().activeWindow as? RotateDialog if (w == null) { LOGGER.log(Level.INFO, "beep!") Toolkit.getDefaultToolkit().beep() return } val outQual = OutQualSpinner(Application.settingsDialog.outputQuality).apply { alignmentX = LEFT_ALIGNMENT } val acc = JPanel().apply { layout = BoxLayout(this, BoxLayout.Y_AXIS) add(Box.createGlue()) add(JLabel("Quality:").apply { alignmentX = LEFT_ALIGNMENT }) add(outQual) } val outName = splitext(w.file.name).first + Application.settingsDialog.outputSuffix + ".jpg" val chooser = JFileChooser().apply { accessory = acc currentDirectory = currentOutputDirectory selectedFile = File(currentOutputDirectory, outName) } if (chooser.showSaveDialog(Application.mainFrame) != JFileChooser.APPROVE_OPTION) { return } currentOutputDirectory = chooser.selectedFile.canonicalFile.parentFile val (name, ext) = splitext(chooser.selectedFile.name) val file = if (ext.toLowerCase() in setOf(".jpg", ".jpeg")) { chooser.selectedFile } else { File(currentOutputDirectory, name + ".jpg") } if (file.exists() && JOptionPane.showConfirmDialog(w, "File ${file.name} already exists. Overwrite?", "Confirm Overwrite", JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) { return } w.useWaitCursor() swingWorker<IOException?> { inBackground { try { /* xxx - ImageIO bug? */ val devNull = java.io.PrintStream(NullOutputStream()) val oldOut = System.out System.setOut(devNull) val oldErr = System.err System.setErr(devNull) val ios = try { ImageIO.createImageOutputStream(file) } finally { System.setErr(oldErr) System.setOut(oldOut) } if (ios == null) throw IOException() /* xxx - end workaround */ ios.use { val writer = ImageIO.getImageWritersByFormatName("jpeg").next() try { val iwp = writer.getDefaultWriteParam().apply { setCompressionMode(ImageWriteParam.MODE_EXPLICIT) setCompressionQuality((outQual.value as Int).toFloat() / 100.0f) } writer.setOutput(it) writer.write(null, IIOImage(w.image, null, null), iwp) } finally { writer.dispose() } } null } catch (e: IOException) { e } } whenDone { w.useNormalCursor() val error = get() if (error == null) { w.close() } else { ioExceptionDialog(w, file, "write", error) } } } } private fun splitext(s: String): Pair<String, String> { val pos = s.lastIndexOf('.') if (pos == -1) { return Pair(s, "") } return Pair(s.substring(0, pos), s.substring(pos)) } } /** * Show an About dialog. */ fun showAboutDialog() { JOptionPane.showMessageDialog(Application.mainFrame, "\nImagePrep\n" + "\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0© MMXX, David W. Barts\n", "About ImagePrep", JOptionPane.PLAIN_MESSAGE) }