diff src/name/blackcap/clipman/SearchDialog.kt @ 27:8aa2dfac27eb

Big reorg; compiled but untested.
author David Barts <n5jrn@me.com>
date Wed, 29 Jan 2020 10:50:07 -0800
parents
children f1fcc1281dad
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/name/blackcap/clipman/SearchDialog.kt	Wed Jan 29 10:50:07 2020 -0800
@@ -0,0 +1,140 @@
+/*
+ * The dialog that controls a search.
+ */
+package name.blackcap.clipman
+
+import java.awt.Color
+import java.awt.Toolkit
+import java.awt.event.ActionEvent
+import java.awt.event.ActionListener
+import javax.swing.*
+import javax.swing.border.*
+import javax.swing.event.DocumentEvent
+import javax.swing.event.DocumentListener
+
+class SearchDialog: JDialog(frame.v), ActionListener, DocumentListener {
+    /* the search term */
+    private val _searchFor = JTextField(50).also {
+        it.border = LineBorder(Color.GRAY, 1)
+        it.horizontalAlignment = JTextField.LEFT
+        it.alignmentX = JTextField.LEFT_ALIGNMENT
+        it.text = ""
+        it.document.addDocumentListener(this)
+    }
+    val searchFor: String
+    get() {
+        return _searchFor.text
+    }
+
+    /* whether or not we should ignore case */
+    private val _ignoreCase = JCheckBox("Ignore case", true)
+    val ignoreCase: Boolean
+    get() {
+        return _ignoreCase.isSelected()
+    }
+
+    /* whether or not searches should wrap around */
+    private val _autoWrap = JCheckBox("Auto wrap", false)
+    val autoWrap: Boolean
+    get() {
+        return _autoWrap.isSelected()
+    }
+
+    /* which direction to search */
+    private val _forwards = JRadioButton("Forward", true)
+    private val _backwards = JRadioButton("Backward", false)
+    private val _direction = ButtonGroup().apply {
+        add(_forwards)
+        add(_backwards)
+    }
+    val direction: PasteboardQueue.Direction
+    get() {
+        if (_forwards.isSelected()) {
+            return PasteboardQueue.Direction.FORWARDS
+        }
+        if (_backwards.isSelected()) {
+            return PasteboardQueue.Direction.BACKWARDS
+        }
+        throw RuntimeException("impossible button state!")
+    }
+
+    /* where to begin searching from. unlike the other properties, this
+       one is read/write. null means to start from the beginning on
+       forward searches, and from the end on backward searches (i.e.
+       search everything) */
+    var origin: PasteboardQueue.Offset? = null
+
+    private val _find = JButton("Find").also {
+        it.actionCommand = "Find"
+        it.addActionListener(this)
+    }
+
+    /* initializer */
+    init {
+        title = "Find"
+        contentPane.apply {
+            add(Box(BoxLayout.Y_AXIS).apply {
+                add(Box(BoxLayout.Y_AXIS).apply {
+                    add(JLabel("Search for").apply {
+                        horizontalAlignment = JLabel.LEFT
+                        alignmentX = JLabel.LEFT_ALIGNMENT
+                    })
+                    add(_searchFor)
+                })
+                add(Box(BoxLayout.X_AXIS).apply {
+                    add(Box(BoxLayout.Y_AXIS).apply {
+                        add(_ignoreCase)
+                        add(_autoWrap)
+                    })
+                    add(Box(BoxLayout.Y_AXIS).apply {
+                        add(_forwards)
+                        add(_backwards)
+                    })
+                })
+                add(_find)
+            })
+        }
+        rootPane.setDefaultButton(_find)
+    }
+
+    override fun actionPerformed(e: ActionEvent) {
+        if (e.actionCommand == "Find") {
+            setVisible(false)
+            find()
+        }
+    }
+
+    override fun setVisible(visible: Boolean) {
+        if (visible) {
+            _searchFor.run {
+                requestFocusInWindow()
+                selectAll()
+            }
+        }
+        super.setVisible(visible)
+    }
+
+    fun find(): Unit {
+        fun doFind(o: PasteboardQueue.Offset?) = queue.v.find(searchFor,
+            direction = direction, foldCase = ignoreCase, origin = o)
+        var result = doFind(origin)
+        if (result == null && origin != null && autoWrap) {
+            result = doFind(null)
+        }
+        if (result == null) {
+            Toolkit.getDefaultToolkit().beep()
+        }
+        origin = result
+    }
+
+    /* changing the search string resets the search origin */
+    override fun changedUpdate(e: DocumentEvent) {
+        if (e.document === _searchFor.document) {
+            origin = null
+        }
+    }
+    override fun insertUpdate(e: DocumentEvent) = changedUpdate(e)
+    override fun removeUpdate(e: DocumentEvent) = changedUpdate(e)
+}
+
+val searchDialog = SearchDialog()
\ No newline at end of file