-
Notifications
You must be signed in to change notification settings - Fork 4
/
App.kt
156 lines (145 loc) · 4.75 KB
/
App.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package example
import java.awt.*
import java.awt.event.ActionEvent
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import javax.swing.*
fun makeUI(): Component {
val tabbedPane = JTabbedPane()
tabbedPane.tabLayoutPolicy = JTabbedPane.SCROLL_TAB_LAYOUT
val addAction: Action = object : AbstractAction() {
override fun actionPerformed(e: ActionEvent) {
(e.source as? JTabbedPane)?.also {
val cnt = it.tabCount
it.addTab("Untitled-$cnt", JScrollPane(JTextArea()))
it.selectedIndex = cnt
}
}
}
val im = tabbedPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
val am = tabbedPane.actionMap
val addKey = "AddTab"
addAction.putValue(Action.ACTION_COMMAND_KEY, addKey)
im.put(KeyStroke.getKeyStroke("ctrl N"), addKey)
am.put(addKey, addAction)
val removeKey = "RemoveTab"
val removeAction = object : AbstractAction() {
override fun actionPerformed(e: ActionEvent) {
(e.source as? JTabbedPane)?.also {
it.remove(it.selectedIndex)
}
}
}
removeAction.putValue(Action.ACTION_COMMAND_KEY, removeKey)
im.put(KeyStroke.getKeyStroke("ctrl W"), removeKey)
am.put(removeKey, removeAction)
tabbedPane.componentPopupMenu = TabbedPanePopupMenu()
val help = "Double-click in tab area to quickly create a new tab."
tabbedPane.addTab("Title", JScrollPane(JTextArea(help)))
tabbedPane.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
val leftButton = e.button == MouseEvent.BUTTON1
val doubleClick = e.clickCount >= 2
val tabs = e.component as JTabbedPane
val idx = tabs.indexAtLocation(e.x, e.y)
val r = getTabAreaBounds(tabs)
val b = idx < 0 && r.contains(e.point)
if (leftButton && doubleClick && b) {
tabs.actionMap[addKey]?.also { a ->
a.actionPerformed(ActionEvent(tabs, ActionEvent.ACTION_PERFORMED, addKey))
}
}
}
})
return JPanel(BorderLayout()).also {
it.add(tabbedPane)
it.preferredSize = Dimension(320, 240)
}
}
private fun getTabAreaBounds(tabbedPane: JTabbedPane): Rectangle {
val r = SwingUtilities.calculateInnerArea(tabbedPane, null)
val cr = tabbedPane.selectedComponent?.bounds ?: Rectangle()
val tp = tabbedPane.tabPlacement
val i1 = UIManager.getInsets("TabbedPane.tabAreaInsets")
val i2 = UIManager.getInsets("TabbedPane.contentBorderInsets")
if (tp == SwingConstants.TOP || tp == SwingConstants.BOTTOM) {
r.height -= cr.height + i1.top + i1.bottom + i2.top + i2.bottom
r.y += if (tp == SwingConstants.TOP) i1.top else cr.y + cr.height + i1.bottom + i2.bottom
} else {
r.width -= cr.width + i1.top + i1.bottom + i2.left + i2.right
r.x += if (tp == SwingConstants.LEFT) i1.top else cr.x + cr.width + i1.bottom + i2.right
}
return r
}
private class TabbedPanePopupMenu : JPopupMenu() {
private val removeTab: JMenuItem
private val closeAll: JMenuItem
private val closeAllButActive: JMenuItem
init {
val addTab = add("New tab")
addTab.actionCommand = "AddTab"
addTab.addActionListener {
(invoker as? JTabbedPane)?.also { tabs ->
val key = addTab.actionCommand
tabs.actionMap[key]?.also {
it.actionPerformed(ActionEvent(tabs, ActionEvent.ACTION_PERFORMED, key))
}
}
}
addSeparator()
removeTab = add("Close")
removeTab.actionCommand = "RemoveTab"
removeTab.addActionListener {
(invoker as? JTabbedPane)?.also { tabs ->
val key = addTab.actionCommand
tabs.actionMap[key]?.also {
it.actionPerformed(ActionEvent(tabs, ActionEvent.ACTION_PERFORMED, key))
}
}
}
addSeparator()
closeAll = add("Close all")
closeAll.addActionListener {
(invoker as? JTabbedPane)?.removeAll()
}
closeAllButActive = add("Close all bat active")
closeAllButActive.addActionListener {
(invoker as? JTabbedPane)?.also {
val idx = it.selectedIndex
val title = it.getTitleAt(idx)
val cmp = it.getComponentAt(idx)
it.removeAll()
it.addTab(title, cmp)
}
}
}
override fun show(
c: Component,
x: Int,
y: Int,
) {
if (c is JTabbedPane) {
removeTab.isEnabled = c.indexAtLocation(x, y) >= 0
closeAll.isEnabled = c.tabCount > 0
closeAllButActive.isEnabled = c.tabCount > 0
super.show(c, x, y)
}
}
}
fun main() {
EventQueue.invokeLater {
runCatching {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName())
}.onFailure {
it.printStackTrace()
Toolkit.getDefaultToolkit().beep()
}
JFrame().apply {
defaultCloseOperation = WindowConstants.EXIT_ON_CLOSE
contentPane.add(makeUI())
pack()
setLocationRelativeTo(null)
isVisible = true
}
}
}