view 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 source

/*
 * 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)
}