Mercurial > cgi-bin > hgweb.cgi > ImagePrep
diff src/name/blackcap/imageprep/Menus.kt @ 0:e0efe7848130
Initial commit. Untested!
author | David Barts <davidb@stashtea.com> |
---|---|
date | Thu, 16 Jul 2020 19:57:23 -0700 |
parents | |
children | 0bded24f746e |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/name/blackcap/imageprep/Menus.kt Thu Jul 16 19:57:23 2020 -0700 @@ -0,0 +1,170 @@ +/* + * Menus. + */ +package name.blackcap.imageprep + +import java.awt.Graphics2D +import java.awt.RenderingHints +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.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.* + +/** + * 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() { + 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 chooser = JFileChooser().apply { + fileFilter = FileNameExtensionFilter("Image files", ImageIO.getReaderFileSuffixes()) + } + if (chooser.showOpenDialog(Application.mainFrame) == JFileChooser.APPROVE_OPTION) { + RotateDialog.makeDialog(chooser.selectedFile) + } + } + + private fun doDiscard() { + val w = FocusManager.currentManager.activeWindow as? RotateDialog + if (w == null) { + Toolkit.defaultToolkit.beep() + return + } + w.setVisible(false) + w.dispose() + } + + private fun doClose() { + val w = FocusManager.currentManager.activeWindow as? RotateDialog + if (w == null) { + Toolkit.defaultToolkit.beep() + return + } + val outName = splitext(w.file.name).first + Settings.outputSuffix + ".jpg" + val chooser = JFileChooser(w).apply { + selectedFile = File( + if (Settings.outputToInputDir) w.file.parent else Settings.outputTo, + outName) + } + if (chooser.showOpenDialog(Application.mainFrame) != JFileChooser.APPROVE_OPTION) { + return + } + val (name, ext) = splitext(chooser.selectedFile.name) + val file = if (ext.toLowerCase() in setOf(".jpg", ".jpeg")) { + chooser.selectedFile + } else { + File(chooser.selectedFile.parent, 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 { + val ios = ImageIO.createImageOutputStream(file) + val writer = ImageIO.getImageWritersByFormatName("jpeg").next() + val iwp = writer.getDefaultWriteParam().apply { + setCompressionMode(ImageWriteParam.MODE_EXPLICIT) + setCompressionQuality(Settings.outputQuality.toFloat() / 100.0f) + } + writer.setOutput(ios) + writer.write(null, IIOImage(w.image, null, null), iwp) + null + } catch (e: IOException) { + e + } + } + whenDone { + w.useNormalCursor() + val error = get() + if (error == null) { + w.setVisible(false) + w.dispose() + } else { + ioExceptionDialog(w, file, "write", e) + } + } + } + } + + 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) +}