view src/name/blackcap/clipman/Menus.kt @ 45:ca8a23bae4fa

Adjust spacing in preferences.
author David Barts <n5jrn@me.com>
date Mon, 10 Feb 2020 06:55:07 -0700
parents 33fbe3a78d84
children 19d9da731c43
line wrap: on
line source

/*
 * Menu-related stuff, pertaining to both the menu bar and popup menus.
 */
package name.blackcap.clipman

import java.awt.Container
import java.awt.Toolkit
import java.awt.event.ActionEvent
import java.awt.event.ActionListener
import java.awt.event.KeyEvent
import javax.swing.*
import kotlin.collections.HashSet

/**
 * Listen to actionEvents from both menu bar and popup menu selections.
 */
class MenuItemListener: ActionListener {
    override fun actionPerformed(e: ActionEvent) {
        when (e.actionCommand) {
            "File.Quit" -> System.exit(0)
            "File.Preferences" -> settingsDialog.setVisible(true)
            "Edit.Clone" -> onlyIfSelected { PasteboardItem.write(it.contents) }
            "Edit.Coerce" -> onlyIfSelected { coerceDialog.setVisible(true) }
            "Edit.Find" -> searchDialog.setVisible(true)
            "Edit.FindAgain" -> searchDialog.find()
            "Help.About" -> showAboutDialog()
            else -> throw RuntimeException("unexpected actionCommand!")
        }
    }

    private fun onlyIfSelected(block: (QueueItem) -> Unit) {
        val selected = queue.v.getSelected()
        if (selected == null) {
            JOptionPane.showMessageDialog(frame.v,
                "No item selected.",
                "Error",
                JOptionPane.ERROR_MESSAGE)
        } else {
            block(selected)
        }
    }
}

val menuItemListener = MenuItemListener()

/**
 * Track menu items that require something to be selected in order
 * to work, and allow them to be enabled and disabled en masse.
 */
class SelectionRequired {
    private val controls = HashSet<JMenuItem>()

    fun add(item: JMenuItem): JMenuItem {
        controls.add(item)
        return item
    }

    private fun setEnabled(state: Boolean) {
        controls.forEach {
            it.setEnabled(state)
        }
    }

    fun enable() = setEnabled(true)

    fun disable() = setEnabled(false)
}

val anyRequired = SelectionRequired()
val styledRequired = SelectionRequired()

/**
 * 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 {
        if (OS.type != OS.MAC) {
            add(JMenu("File").apply {
                add(JMenuItem("Quit").apply {
                    actionCommand = "File.Quit"
                    addActionListener(menuItemListener)
                    makeShortcut(KeyEvent.VK_Q)
                })
                add(JMenuItem("Preferences…").apply {
                    actionCommand = "File.Preferences"
                    addActionListener(menuItemListener)
                    makeShortcut(KeyEvent.VK_COMMA)
                })
            })
        }
        add(JMenu("Edit").apply {
            add(anyRequired.add(JMenuItem("Clone").apply {
                setEnabled(false)
                actionCommand = "Edit.Clone"
                addActionListener(menuItemListener)
                makeShortcut(KeyEvent.VK_C)
            }))
            add(styledRequired.add(JMenuItem("Coerce…").apply {
                setEnabled(false)
                actionCommand = "Edit.Coerce"
                addActionListener(menuItemListener)
                makeShortcut(KeyEvent.VK_K)
            }))
            add(JMenuItem("Find…").apply {
                actionCommand = "Edit.Find"
                addActionListener(menuItemListener)
                makeShortcut(KeyEvent.VK_F)
            })
            add(JMenuItem("Find Again").apply {
                actionCommand = "Edit.FindAgain"
                addActionListener(menuItemListener)
                makeShortcut(KeyEvent.VK_G)
            })
        })
        if (OS.type != OS.MAC) {
            add(JMenu("Help").apply {
                add(JMenuItem("About ClipMan…").apply {
                    actionCommand = "Help.About"
                    addActionListener(menuItemListener)
                })
            })
        }
    }

    fun getMenu(name: String): JMenu? {
        subElements.forEach {
            val jmenu = it.component as? JMenu
            if (jmenu?.text == name) {
                return jmenu
            }
        }
        return null
    }
}

val menuBar = MyMenuBar()

/**
 * The popup menu we display when the user requests so atop a clipboard
 * item.
 */
class MyPopupMenu: JPopupMenu() {
    init {
        add(anyRequired.add(JMenuItem("Clone").apply {
            actionCommand = "Edit.Clone"
            addActionListener(menuItemListener)
        }))
        add(styledRequired.add(JMenuItem("Coerce…").apply {
            actionCommand = "Edit.Coerce"
            addActionListener(menuItemListener)
        }))
    }
}

val popupMenu = MyPopupMenu()

/**
 * Show an About dialog.
 */
fun showAboutDialog() {
    JOptionPane.showMessageDialog(frame.v,
        "ClipMan, a clipboard manager.\n"
        + "© MMXX, David W. Barts",
        "About ClipMan",
        JOptionPane.PLAIN_MESSAGE)
}