Mercurial > cgi-bin > hgweb.cgi > ClipMan
comparison src/name/blackcap/clipman/Main.kt @ 9:8fcff14defa2
Stomp out race conditions and set width adaptively.
author | David Barts <n5jrn@me.com> |
---|---|
date | Sun, 19 Jan 2020 15:43:01 -0800 |
parents | 7715ff59f053 |
children | e7e067f5b649 |
comparison
equal
deleted
inserted
replaced
8:7715ff59f053 | 9:8fcff14defa2 |
---|---|
13 import java.awt.event.WindowEvent | 13 import java.awt.event.WindowEvent |
14 import java.awt.event.WindowListener | 14 import java.awt.event.WindowListener |
15 import java.util.Date | 15 import java.util.Date |
16 import java.util.logging.Level | 16 import java.util.logging.Level |
17 import java.util.logging.Logger | 17 import java.util.logging.Logger |
18 import java.util.concurrent.Semaphore | |
18 import javax.swing.* | 19 import javax.swing.* |
19 import javax.swing.border.* | 20 import javax.swing.border.* |
20 import javax.swing.text.JTextComponent | 21 import javax.swing.text.JTextComponent |
21 import kotlin.concurrent.thread | 22 import kotlin.concurrent.thread |
22 import org.jsoup.Jsoup | 23 import org.jsoup.Jsoup |
26 val MYNAME = "ClipMan" | 27 val MYNAME = "ClipMan" |
27 | 28 |
28 /* default sizes */ | 29 /* default sizes */ |
29 val CPWIDTH = 640 | 30 val CPWIDTH = 640 |
30 val CPHEIGHT = 480 | 31 val CPHEIGHT = 480 |
31 val TPWIDTH = CPWIDTH - 60 | 32 |
33 /* border widths */ | |
34 val PANEL_BORDER = 9 | |
35 val OUTER_BORDER = 9 /* must be 6 or more */ | |
36 val INNER_BORDER = 1 | |
37 val MARGIN_BORDER = 3 | |
32 | 38 |
33 /* kills the updating thread (and does a system exit) when needed */ | 39 /* kills the updating thread (and does a system exit) when needed */ |
34 class KillIt(val thr: Thread) : WindowListener { | 40 class KillIt(val thr: Thread) : WindowListener { |
35 // events we don't care about | 41 // events we don't care about |
36 override fun windowActivated(e: WindowEvent) {} | 42 override fun windowActivated(e: WindowEvent) {} |
49 } | 55 } |
50 | 56 |
51 /* the updating thread */ | 57 /* the updating thread */ |
52 class UpdateIt(val queue: PasteboardQueue, val interval: Int): Thread() { | 58 class UpdateIt(val queue: PasteboardQueue, val interval: Int): Thread() { |
53 @Volatile var enabled = true | 59 @Volatile var enabled = true |
54 private val outerBorder = MatteBorder(3, 9, 9, 9, queue.parent.background) | 60 private val outerBorder = |
61 MatteBorder(OUTER_BORDER-6, OUTER_BORDER, OUTER_BORDER, OUTER_BORDER, | |
62 queue.parent.background) | |
55 private val stdBorder = | 63 private val stdBorder = |
56 CompoundBorder(LineBorder(Color.GRAY, 1), EmptyBorder(3, 3, 3, 3)) | 64 CompoundBorder(LineBorder(Color.GRAY, INNER_BORDER), |
65 EmptyBorder(MARGIN_BORDER, MARGIN_BORDER, MARGIN_BORDER, MARGIN_BORDER)) | |
57 | 66 |
58 override fun run() { | 67 override fun run() { |
59 var oldContents = "" | 68 var oldContents = "" |
60 var newContents = "" | 69 var newContents = "" |
61 while (true) { | 70 while (true) { |
65 newContents = when (contents) { | 74 newContents = when (contents) { |
66 is PasteboardItem.Plain -> contents.plain | 75 is PasteboardItem.Plain -> contents.plain |
67 is PasteboardItem.HTML -> contents.plain | 76 is PasteboardItem.HTML -> contents.plain |
68 } | 77 } |
69 if (oldContents != newContents) { | 78 if (oldContents != newContents) { |
79 var stdWidth: Int? = null | |
80 inSynSwingThread { | |
81 stdWidth = queue.parent.size.width - 2 * (PANEL_BORDER+OUTER_BORDER+INNER_BORDER+MARGIN_BORDER) | |
82 } | |
70 var widget = JPanel().apply { | 83 var widget = JPanel().apply { |
71 layout = BoxLayout(this, BoxLayout.Y_AXIS) | 84 layout = BoxLayout(this, BoxLayout.Y_AXIS) |
72 background = queue.parent.background | 85 background = queue.parent.background |
73 border = outerBorder | 86 border = outerBorder |
74 } | 87 } |
78 add(JTextPane().apply { | 91 add(JTextPane().apply { |
79 contentType = "text/plain" | 92 contentType = "text/plain" |
80 text = contents.plain | 93 text = contents.plain |
81 font = Font(Font.MONOSPACED, Font.PLAIN, 14) | 94 font = Font(Font.MONOSPACED, Font.PLAIN, 14) |
82 border = stdBorder | 95 border = stdBorder |
83 autoSize(TPWIDTH) | 96 autoSize(stdWidth!!) |
84 setEditable(false) | 97 setEditable(false) |
85 alignmentX = JTextPane.LEFT_ALIGNMENT | 98 alignmentX = JTextPane.LEFT_ALIGNMENT |
86 }) | 99 }) |
87 } | 100 } |
88 is PasteboardItem.HTML -> widget.run { | 101 is PasteboardItem.HTML -> widget.run { |
90 add(JTextPane().apply { | 103 add(JTextPane().apply { |
91 contentType = "text/html" | 104 contentType = "text/html" |
92 toolTipText = "Styled text" | 105 toolTipText = "Styled text" |
93 text = scrub(contents.html) | 106 text = scrub(contents.html) |
94 border = stdBorder | 107 border = stdBorder |
95 autoSize(TPWIDTH) | 108 autoSize(stdWidth!!) |
96 setEditable(false) | 109 setEditable(false) |
97 alignmentX = JTextPane.LEFT_ALIGNMENT | 110 alignmentX = JTextPane.LEFT_ALIGNMENT |
98 }) | 111 }) |
99 } | 112 } |
100 } | 113 } |
134 LOGGER.log(Level.INFO, "beginning execution") | 147 LOGGER.log(Level.INFO, "beginning execution") |
135 setLookFeel() | 148 setLookFeel() |
136 val frame = JFrame(MYNAME) | 149 val frame = JFrame(MYNAME) |
137 val con = JPanel().apply { | 150 val con = JPanel().apply { |
138 layout = BoxLayout(this, BoxLayout.Y_AXIS) | 151 layout = BoxLayout(this, BoxLayout.Y_AXIS) |
139 border = EmptyBorder(9, 9, 9, 9) | 152 border = EmptyBorder(PANEL_BORDER, PANEL_BORDER, PANEL_BORDER, PANEL_BORDER) |
140 background = frame.background | 153 background = frame.background |
141 } | 154 } |
142 inSwingThread { | 155 inSynSwingThread { |
143 frame.apply { | 156 frame.apply { |
144 contentPane.add( | 157 contentPane.add( |
145 JScrollPane(con).apply { | 158 JScrollPane(con).apply { |
146 verticalScrollBarPolicy = ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS | 159 verticalScrollBarPolicy = ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS |
147 horizontalScrollBarPolicy = ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER | 160 horizontalScrollBarPolicy = ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER |
165 | 178 |
166 fun inSwingThread(block: () -> Unit) { | 179 fun inSwingThread(block: () -> Unit) { |
167 SwingUtilities.invokeLater(Runnable(block)) | 180 SwingUtilities.invokeLater(Runnable(block)) |
168 } | 181 } |
169 | 182 |
183 fun inSynSwingThread(block: () -> Unit) { | |
184 val ready = Semaphore(0) | |
185 inSwingThread { | |
186 block() | |
187 ready.release() | |
188 } | |
189 ready.acquire() | |
190 } | |
191 | |
170 fun JTextComponent.autoSize(width: Int): Unit { | 192 fun JTextComponent.autoSize(width: Int): Unit { |
171 val SLOP = 10 | 193 val SLOP = 10 |
172 val dim = Dimension(width, width) | 194 val dim = Dimension(width, width) |
173 preferredSize = dim | 195 preferredSize = dim |
174 size = dim | 196 size = dim |