27
|
1 /*
|
|
2 * The dialog that controls a search.
|
|
3 */
|
|
4 package name.blackcap.clipman
|
|
5
|
|
6 import java.awt.Color
|
|
7 import java.awt.Toolkit
|
|
8 import java.awt.event.ActionEvent
|
|
9 import java.awt.event.ActionListener
|
|
10 import javax.swing.*
|
|
11 import javax.swing.border.*
|
|
12 import javax.swing.event.DocumentEvent
|
|
13 import javax.swing.event.DocumentListener
|
|
14
|
|
15 class SearchDialog: JDialog(frame.v), ActionListener, DocumentListener {
|
|
16 /* the search term */
|
|
17 private val _searchFor = JTextField(50).also {
|
|
18 it.border = LineBorder(Color.GRAY, 1)
|
|
19 it.horizontalAlignment = JTextField.LEFT
|
|
20 it.alignmentX = JTextField.LEFT_ALIGNMENT
|
|
21 it.text = ""
|
|
22 it.document.addDocumentListener(this)
|
|
23 }
|
|
24 val searchFor: String
|
|
25 get() {
|
|
26 return _searchFor.text
|
|
27 }
|
|
28
|
|
29 /* whether or not we should ignore case */
|
|
30 private val _ignoreCase = JCheckBox("Ignore case", true)
|
|
31 val ignoreCase: Boolean
|
|
32 get() {
|
|
33 return _ignoreCase.isSelected()
|
|
34 }
|
|
35
|
|
36 /* whether or not searches should wrap around */
|
|
37 private val _autoWrap = JCheckBox("Auto wrap", false)
|
|
38 val autoWrap: Boolean
|
|
39 get() {
|
|
40 return _autoWrap.isSelected()
|
|
41 }
|
|
42
|
|
43 /* which direction to search */
|
|
44 private val _forwards = JRadioButton("Forward", true)
|
|
45 private val _backwards = JRadioButton("Backward", false)
|
|
46 private val _direction = ButtonGroup().apply {
|
|
47 add(_forwards)
|
|
48 add(_backwards)
|
|
49 }
|
|
50 val direction: PasteboardQueue.Direction
|
|
51 get() {
|
|
52 if (_forwards.isSelected()) {
|
|
53 return PasteboardQueue.Direction.FORWARDS
|
|
54 }
|
|
55 if (_backwards.isSelected()) {
|
|
56 return PasteboardQueue.Direction.BACKWARDS
|
|
57 }
|
|
58 throw RuntimeException("impossible button state!")
|
|
59 }
|
|
60
|
|
61 /* where to begin searching from. unlike the other properties, this
|
|
62 one is read/write. null means to start from the beginning on
|
|
63 forward searches, and from the end on backward searches (i.e.
|
|
64 search everything) */
|
|
65 var origin: PasteboardQueue.Offset? = null
|
|
66
|
|
67 private val _find = JButton("Find").also {
|
|
68 it.actionCommand = "Find"
|
|
69 it.addActionListener(this)
|
|
70 }
|
|
71
|
|
72 /* initializer */
|
|
73 init {
|
|
74 title = "Find"
|
|
75 contentPane.apply {
|
|
76 add(Box(BoxLayout.Y_AXIS).apply {
|
|
77 add(Box(BoxLayout.Y_AXIS).apply {
|
|
78 add(JLabel("Search for").apply {
|
|
79 horizontalAlignment = JLabel.LEFT
|
|
80 alignmentX = JLabel.LEFT_ALIGNMENT
|
|
81 })
|
|
82 add(_searchFor)
|
|
83 })
|
|
84 add(Box(BoxLayout.X_AXIS).apply {
|
|
85 add(Box(BoxLayout.Y_AXIS).apply {
|
|
86 add(_ignoreCase)
|
|
87 add(_autoWrap)
|
|
88 })
|
|
89 add(Box(BoxLayout.Y_AXIS).apply {
|
|
90 add(_forwards)
|
|
91 add(_backwards)
|
|
92 })
|
|
93 })
|
|
94 add(_find)
|
|
95 })
|
|
96 }
|
|
97 rootPane.setDefaultButton(_find)
|
|
98 }
|
|
99
|
|
100 override fun actionPerformed(e: ActionEvent) {
|
|
101 if (e.actionCommand == "Find") {
|
|
102 setVisible(false)
|
|
103 find()
|
|
104 }
|
|
105 }
|
|
106
|
|
107 override fun setVisible(visible: Boolean) {
|
|
108 if (visible) {
|
|
109 _searchFor.run {
|
|
110 requestFocusInWindow()
|
|
111 selectAll()
|
|
112 }
|
|
113 }
|
|
114 super.setVisible(visible)
|
|
115 }
|
|
116
|
|
117 fun find(): Unit {
|
|
118 fun doFind(o: PasteboardQueue.Offset?) = queue.v.find(searchFor,
|
|
119 direction = direction, foldCase = ignoreCase, origin = o)
|
|
120 var result = doFind(origin)
|
|
121 if (result == null && origin != null && autoWrap) {
|
|
122 result = doFind(null)
|
|
123 }
|
|
124 if (result == null) {
|
|
125 Toolkit.getDefaultToolkit().beep()
|
|
126 }
|
|
127 origin = result
|
|
128 }
|
|
129
|
|
130 /* changing the search string resets the search origin */
|
|
131 override fun changedUpdate(e: DocumentEvent) {
|
|
132 if (e.document === _searchFor.document) {
|
|
133 origin = null
|
|
134 }
|
|
135 }
|
|
136 override fun insertUpdate(e: DocumentEvent) = changedUpdate(e)
|
|
137 override fun removeUpdate(e: DocumentEvent) = changedUpdate(e)
|
|
138 }
|
|
139
|
|
140 val searchDialog = SearchDialog() |