view src/name/blackcap/clipman/SearchDialog.kt @ 63:8c6d6ad92aa1
last-old-threading
Commit most recent changes.
author |
David Barts <n5jrn@me.com> |
date |
Sun, 12 Jan 2025 10:22:05 -0800 (11 days ago) |
parents |
19d9da731c43 |
children |
|
line source
/*
* 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.event.DocumentEvent
import javax.swing.event.DocumentListener
class SearchDialog: JDialog(Application.frame), ActionListener, DocumentListener {
/* the search term */
private val _searchFor = JTextField(25).also {
it.border = BorderFactory.createLineBorder(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!")
}
/* standard spacing between elements (10 pixels ≅ 1/7") and half that */
private val BW = 5
private val BW2 = 10
/* 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)
}
private val _cancel = JButton("Cancel").also {
it.actionCommand = "Cancel"
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)
alignmentX = Box.CENTER_ALIGNMENT
border = BorderFactory.createEmptyBorder(BW2, BW2, BW, BW2)
})
add(Box(BoxLayout.X_AXIS).apply {
add(Box.createGlue())
add(Box(BoxLayout.Y_AXIS).apply {
add(JLabel("Settings:").apply {
horizontalAlignment = JLabel.CENTER
alignmentX = JLabel.LEFT_ALIGNMENT
})
add(_ignoreCase)
add(_autoWrap)
})
add(Box.createGlue())
add(Box(BoxLayout.Y_AXIS).apply {
add(JLabel("Direction:").apply {
horizontalAlignment = JLabel.CENTER
alignmentX = JLabel.LEFT_ALIGNMENT
})
add(_forwards)
add(_backwards)
})
add(Box.createGlue())
alignmentX = Box.CENTER_ALIGNMENT
border = BorderFactory.createEmptyBorder(BW, BW2, BW, BW2)
})
add(Box(BoxLayout.X_AXIS).apply {
add(Box.createGlue())
add(_cancel)
add(Box.createGlue())
add(_find)
add(Box.createGlue())
border = BorderFactory.createEmptyBorder(BW, BW2, BW2, BW2)
})
})
}
rootPane.setDefaultButton(_find)
pack()
setResizable(false)
}
override fun actionPerformed(e: ActionEvent) {
when (e.actionCommand) {
"Find" -> {
setVisible(false)
find()
}
"Cancel" -> setVisible(false)
}
}
override fun setVisible(visible: Boolean) {
if (visible) {
_searchFor.run {
requestFocusInWindow()
selectAll()
}
}
super.setVisible(visible)
}
fun find(): Unit {
if (searchFor.isEmpty()) {
Toolkit.getDefaultToolkit().beep()
origin = null
return
}
fun doFind(o: PasteboardQueue.Offset?) = Application.queue.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 = null
} else {
origin = when(direction) {
PasteboardQueue.Direction.FORWARDS ->
PasteboardQueue.Offset(result.inQueue, result.inItem + 1)
PasteboardQueue.Direction.BACKWARDS ->
if (result.inItem == 0) {
if (result.inQueue == 0) null else PasteboardQueue.Offset(result.inQueue - 1, -1)
} else {
PasteboardQueue.Offset(result.inQueue, result.inItem - 1)
}
}
}
}
/* 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)
}