20
|
1 /*
|
|
2 * The dialog that controls font corecion.
|
|
3 */
|
|
4 package name.blackcap.imageprep
|
|
5
|
|
6 import java.awt.Dimension
|
|
7 import java.awt.event.ActionEvent
|
|
8 import java.awt.event.ActionListener
|
|
9 import java.io.BufferedWriter
|
|
10 import java.io.File
|
|
11 import java.io.FileOutputStream
|
|
12 import java.io.IOException
|
|
13 import java.io.OutputStreamWriter
|
|
14 import java.util.Hashtable
|
|
15 import java.util.Properties
|
|
16 import java.util.logging.Level
|
|
17 import java.util.logging.Logger
|
|
18 import javax.swing.*
|
|
19 import javax.swing.event.ChangeEvent
|
|
20 import javax.swing.event.ChangeListener
|
|
21 import kotlin.math.log10
|
|
22 import kotlin.math.pow
|
|
23 import kotlin.math.roundToInt
|
|
24 import kotlin.text.toInt
|
|
25
|
|
26 /* work around name shadowing */
|
|
27 private val _PROPS = PROPERTIES
|
|
28
|
|
29 class SettingsDialog: JDialog(Application.mainFrame) {
|
|
30 /* maximum allowed dimension in output */
|
|
31 private val _maxDimension = MaxDimSpinner(_PROPS.getInt("maxDimension"))
|
|
32 val maxDimension: Int
|
|
33 get() {
|
|
34 return _maxDimension.value as Int
|
|
35 }
|
|
36
|
|
37 /* JPEG output quality */
|
|
38 private val _outputQuality = OutQualSpinner(_PROPS.getInt("outputQuality"))
|
|
39 val outputQuality: Int
|
|
40 get() {
|
|
41 return _outputQuality.value as Int
|
|
42 }
|
|
43
|
|
44 /* file name output suffix */
|
|
45 private val _outputSuffix = JTextField(_PROPS.getProperty("outputSuffix"), 24).apply {
|
|
46 noTaller()
|
|
47 }
|
|
48 val outputSuffix: String
|
|
49 get() {
|
|
50 return _outputSuffix.text
|
|
51 }
|
|
52
|
|
53 /* output to input dir? */
|
|
54 private val otid = _PROPS.getBoolean("outputToInputDir")
|
21
|
55 private val outputToInputButton = JRadioButton("Create output file in same folder as input.", otid).apply {
|
|
56 alignmentX = LEFT_ALIGNMENT
|
|
57 }
|
20
|
58 val outputToInputDir: Boolean
|
|
59 get() {
|
|
60 return outputToInputButton.isSelected()
|
|
61 }
|
|
62
|
|
63 /* output to some other directory */
|
21
|
64 private val outputToButton = JRadioButton("Create output file in:", !otid).apply {
|
|
65 alignmentX = LEFT_ALIGNMENT
|
|
66 }
|
20
|
67
|
|
68 /* name of the other directory */
|
|
69 private val oto = _getOutputTo()
|
|
70 protected val outputToText = JTextField(oto, 40).apply {
|
|
71 setEditable(false)
|
|
72 noTaller()
|
|
73 }
|
|
74
|
|
75 /* chooser for other directory */
|
|
76 private val _outputTo = JFileChooser(oto).apply {
|
|
77 fileSelectionMode = JFileChooser.DIRECTORIES_ONLY
|
|
78 setMultiSelectionEnabled(false)
|
|
79 }
|
|
80 val outputTo: String
|
|
81 get() {
|
|
82 return _outputTo.selectedFile?.getCanonicalPath() ?: oto
|
|
83 }
|
|
84
|
|
85 /* button to change that other directory */
|
|
86 protected val changeOutputTo = JButton("Change").also {
|
|
87 it.noTaller()
|
|
88 it.addActionListener(ActionListener {
|
|
89 val status = _outputTo.showOpenDialog(this)
|
|
90 if (status == JFileChooser.APPROVE_OPTION) {
|
|
91 val path = outputTo
|
|
92 outputToText.text = path
|
|
93 }
|
|
94 })
|
|
95 it.setEnabled(!otid)
|
|
96 }
|
|
97
|
|
98 /* radio button group */
|
|
99 protected val buttonGroup = ButtonGroup().apply {
|
|
100 add(outputToButton)
|
|
101 add(outputToInputButton)
|
|
102 }
|
|
103
|
|
104 /* standard spacing between elements (10 pixels ≅ 1/7") and half that */
|
|
105 private val BW = 5
|
|
106 private val BW2 = 10
|
|
107
|
|
108 /* buttons */
|
|
109 private val _ok = JButton("OK").also {
|
|
110 it.noTaller()
|
|
111 it.addActionListener(ActionListener {
|
|
112 writeProperties()
|
|
113 setVisible(false)
|
|
114 })
|
|
115 }
|
|
116
|
|
117 private val _cancel = JButton("Cancel").also {
|
|
118 it.noTaller()
|
|
119 it.addActionListener(ActionListener {
|
|
120 revertValues()
|
|
121 setVisible(false)
|
|
122 })
|
|
123 }
|
|
124
|
|
125 /* initializer */
|
|
126 init {
|
|
127 title = "Preferences"
|
|
128 contentPane.apply {
|
|
129 layout = BoxLayout(this, BoxLayout.Y_AXIS)
|
|
130 add(Box(BoxLayout.X_AXIS).apply {
|
21
|
131 alignmentX = LEFT_ALIGNMENT
|
20
|
132 border = BorderFactory.createEmptyBorder(BW2, BW2, BW, BW2)
|
21
|
133 add(leftLabel("Maximum dimension: "))
|
20
|
134 add(_maxDimension)
|
|
135 add(Box.createGlue())
|
21
|
136 add(leftLabel("Output quality: "))
|
20
|
137 add(_outputQuality)
|
|
138 })
|
|
139 add(Box(BoxLayout.X_AXIS).apply {
|
21
|
140 alignmentX = LEFT_ALIGNMENT
|
20
|
141 border = BorderFactory.createEmptyBorder(BW, BW2, BW, BW2)
|
21
|
142 add(leftLabel("Output filename suffix: "))
|
20
|
143 add(_outputSuffix)
|
|
144 add(Box.createGlue())
|
|
145 })
|
|
146 add(Box(BoxLayout.Y_AXIS).apply {
|
21
|
147 alignmentX = LEFT_ALIGNMENT
|
|
148 border = BorderFactory.createEmptyBorder(BW, BW2, BW, BW2)
|
20
|
149 add(outputToInputButton)
|
|
150 add(outputToButton)
|
|
151 add(Box(BoxLayout.X_AXIS).apply {
|
21
|
152 alignmentX = LEFT_ALIGNMENT
|
20
|
153 add(outputToText)
|
|
154 add(changeOutputTo)
|
|
155 add(Box.createGlue())
|
|
156 })
|
|
157 })
|
|
158 add(Box(BoxLayout.X_AXIS).apply {
|
21
|
159 alignmentX = LEFT_ALIGNMENT
|
|
160 border = BorderFactory.createEmptyBorder(BW, BW2, BW2, BW2)
|
|
161 add(Box.createGlue())
|
20
|
162 add(_cancel)
|
|
163 add(Box.createGlue())
|
|
164 add(_ok)
|
21
|
165 add(Box.createGlue())
|
20
|
166 })
|
|
167 }
|
|
168 rootPane.setDefaultButton(_ok)
|
|
169 pack()
|
|
170 setResizable(false)
|
|
171 }
|
|
172
|
|
173 private fun leftLabel(text: String) = JLabel(text).apply {
|
|
174 alignmentX = JLabel.LEFT_ALIGNMENT
|
|
175 }
|
|
176
|
|
177 private fun revertValues()
|
|
178 {
|
|
179 _maxDimension.value = _PROPS.getInt("maxDimension")
|
|
180 _outputQuality.value = _PROPS.getInt("outputQuality")
|
|
181 _outputSuffix.text = _PROPS.getProperty("outputSuffix")
|
|
182 val otid = _PROPS.getBoolean("outputToInputDir")
|
|
183 outputToInputButton.setSelected(otid)
|
|
184 outputToButton.setSelected(!otid)
|
|
185 val oto = _getOutputTo()
|
|
186 outputToText.text = oto
|
|
187 _outputTo.selectedFile = File(oto)
|
|
188 }
|
|
189
|
|
190 private fun writeProperties()
|
|
191 {
|
|
192 _PROPS.setInt("maxDimension", maxDimension)
|
|
193 _PROPS.setInt("outputQuality", outputQuality)
|
|
194 _PROPS.setProperty("outputSuffix", outputSuffix)
|
|
195 _PROPS.setBoolean("outputToInputDir", outputToInputDir)
|
|
196 _PROPS.setProperty("outputTo", outputTo)
|
|
197 try {
|
|
198 BufferedWriter(OutputStreamWriter(FileOutputStream(PROP_FILE), CHARSET)).use {
|
|
199 _PROPS.store(it, " -*- coding: ${CHARSET} -*-")
|
|
200 }
|
|
201 } catch (e: IOException) {
|
|
202 LOGGER.log(Level.WARNING, "IOException writing properties file")
|
|
203 val message = e.message
|
|
204 if (message != null && !message.isEmpty()) {
|
|
205 LOGGER.log(Level.WARNING, message)
|
|
206 }
|
|
207 JOptionPane.showMessageDialog(Application.mainFrame,
|
|
208 "Unable to write settings.",
|
|
209 "Error",
|
|
210 JOptionPane.ERROR_MESSAGE)
|
|
211 }
|
|
212 }
|
|
213
|
21
|
214 private fun _getOutputTo(): String {
|
|
215 val p = _PROPS.getProperty("outputTo")
|
|
216 return if (p != null) tilde(p) else System.getProperty("user.dir")
|
|
217 }
|
20
|
218 }
|
|
219
|
|
220 fun Properties.getString(key: String): String = getProperty(key) as String
|
|
221
|
|
222 fun Properties.getInt(key: String): Int = getString(key).toInt()
|
|
223
|
|
224 fun Properties.setInt(key: String, value: Int): Unit {
|
|
225 setProperty(key, value.toString())
|
|
226 }
|
|
227
|
|
228 fun Properties.getBoolean(key: String): Boolean {
|
|
229 val raw = getProperty(key)
|
|
230 if (raw.isNullOrEmpty())
|
|
231 return false
|
|
232 val c1 = raw[0].toLowerCase()
|
|
233 return c1 == 't' || c1 == 'y'
|
|
234 }
|
|
235
|
|
236 fun Properties.setBoolean(key: String, value: Boolean): Unit {
|
|
237 setProperty(key, value.toString())
|
|
238 }
|
|
239
|
|
240 fun JComponent.noTaller() {
|
|
241 maximumSize = Dimension(maximumSize.width, preferredSize.height)
|
|
242 }
|