diff src/name/blackcap/exifwasher/SettingsDialog.kt @ 5:dc1f4359659d

Got it compiling.
author David Barts <n5jrn@me.com>
date Thu, 09 Apr 2020 18:20:34 -0700
parents 19c381c536ec
children aafc9c127c7b
line wrap: on
line diff
--- a/src/name/blackcap/exifwasher/SettingsDialog.kt	Wed Apr 08 21:31:30 2020 -0700
+++ b/src/name/blackcap/exifwasher/SettingsDialog.kt	Thu Apr 09 18:20:34 2020 -0700
@@ -6,71 +6,79 @@
 import java.awt.Toolkit
 import java.awt.event.ActionEvent
 import java.awt.event.ActionListener
+import java.io.BufferedWriter
 import java.io.File
+import java.io.FileOutputStream
 import java.io.IOException
+import java.io.OutputStreamWriter
+import java.util.Properties
 import java.util.logging.Level
 import java.util.logging.Logger
 import javax.swing.*
 import javax.swing.event.ListDataEvent
 import javax.swing.event.ListDataListener
+import javax.swing.event.ListSelectionListener
 import kotlin.text.toBoolean
 
 import name.blackcap.exifwasher.exiv2.*
 
+/* work around name shadowing */
+private val _PROPS = PROPERTIES
+
 class SettingsDialog : JDialog(Application.mainFrame) {
-    private val BW = 9
-    private val BW2 = BW * 2
+    protected val BW = 9
+    protected val BW2 = BW * 2
 
     /* where to send output, if not outputToInputDir */
-    private var _outputTo = PROPERTIES.getProperty("outputTo")
-    private var _dOutputTo = DPROPERTIES.getProperty("outputTo")
+    protected var _outputTo = _PROPS.getProperty("outputTo")
+    protected var _dOutputTo = DPROPERTIES.getProperty("outputTo")
     val outputTo: String
     get() = _outputTo
 
     /* make output where input was found */
-    private var _outputToInputDir = (PROPERTIES.getProperty("outputToInputDir") ?: "false").toBoolean()
-    private var _dOutputToInputDir = (DPROPERTIES.getProperty("outputToInputDir") ?: "false").toBoolean()
+    protected var _outputToInputDir = _PROPS.getProperty("outputToInputDir", "false").toBoolean()
+    protected var _dOutputToInputDir = DPROPERTIES.getProperty("outputToInputDir", "false").toBoolean()
     val outputToInputDir: Boolean
     get() = _outputToInputDir
 
     /* the whitelist of allowed Exif tags */
-    private var _whitelist = Whitelist.parse(PROPERTIES.getProperty("whitelist") :? "")
+    protected var _whitelist = Whitelist.parse(_PROPS.getProperty("whitelist", ""))
     val whitelist: Whitelist
     get() = _whitelist
 
     /* the default whitelist, for factory resets */
-    private val _oWhitelist = _whitelist.clone()
-    private val _dWhitelist = Whitelist.parse(DPROPERTIES.getProperty("whitelist") :? "")
+    protected val _oWhitelist = _whitelist.clone()
+    protected val _dWhitelist = Whitelist.parse(DPROPERTIES.getProperty("whitelist", ""))
 
     /* radio buttons to choose output directory policy */
-    private val outputToButton = JRadioButton("Output to:", !outputToInputDir).apply {
+    protected val outputToButton = JRadioButton("Output to:", !outputToInputDir).apply {
         addActionListener(ActionListener { setOutputOpts(isSelected()) })
     }
-    private val outputToInputButton = JRadioButton(
+    protected val outputToInputButton = JRadioButton(
       "Output to directory containing input file.", outputToInputDir).apply {
         addActionListener(ActionListener { setOutputOpts(!isSelected()) })
     }
-    private val buttonGroup = ButtonGroup().apply {
+    protected val buttonGroup = ButtonGroup().apply {
         add(outputToButton)
         add(outputToInputButton)
     }
-    private fun setOutputOpts(toSpecific: Boolean) {
+    protected fun setOutputOpts(toSpecific: Boolean) {
         _outputToInputDir = !toSpecific
         changeOutputTo.setEnabled(toSpecific)
     }
 
     /* displays the OutputTo directory */
-    private val outputToText = JTextField(outputTo, 50).apply {
+    protected val outputToText = JTextField(outputTo, 50).apply {
         setEditable(false)
     }
 
     /* pops up to change the above directory */
-    private val outputToChooser = JFileChooser(outputToText.text).apply {
-        fileSelectionMode = DIRECTORIES_ONLY
+    protected val outputToChooser = JFileChooser(outputToText.text).apply {
+        fileSelectionMode = JFileChooser.DIRECTORIES_ONLY
     }
 
     /* requests the OutputTo directory be changed */
-    private val changeOutputTo = JButton("Change").also {
+    protected val changeOutputTo = JButton("Change").also {
         it.addActionListener(ActionListener {
             val status = outputToChooser.showOpenDialog(this)
             if (status == JFileChooser.APPROVE_OPTION) {
@@ -82,33 +90,33 @@
     }
 
     /* bottom buttons to restore defaults, cancel, save */
-    private val restoreButton = JButton("Restore All Defaults").also {
+    protected val restoreButton = JButton("Restore All Defaults").apply {
         addActionListener(ActionListener {
             restore(_dOutputToInputDir, _dOutputTo, _dWhitelist)
-        }
+        })
     }
-    private val cancelButton = JButton("Cancel").also {
+    protected val cancelButton = JButton("Cancel").apply {
         addActionListener(ActionListener {
             setVisible(false)
             restore(outputToInputDir, outputTo, whitelist)
         })
     }
-    private val saveButton = JButton("Save").also {
+    protected val saveButton = JButton("Save").apply {
         addActionListener(ActionListener {
             setVisible(false)
             writeProperties()
         })
     }
 
-    private fun writeProperties() {
-        PROPERTIES.run {
+    protected fun writeProperties() {
+        _PROPS.run {
             setProperty("outputTo", outputTo)
             setProperty("outputToInputDir", outputToInputDir.toString())
             setProperty("whitelist", whitelist.toString())
         }
         try {
             BufferedWriter(OutputStreamWriter(FileOutputStream(PROP_FILE), CHARSET)).use {
-                PROPERTIES.store(it, null)
+                _PROPS.store(it, null)
             }
         } catch (e: IOException) {
             LOGGER.log(Level.SEVERE, "unable to write settings", e)
@@ -119,7 +127,7 @@
         }
     }
 
-    private fun restore(outputToInput: Boolean, output: String, wl: Whitelist) {
+    protected fun restore(outputToInput: Boolean, output: String, wl: Whitelist) {
         outputToButton.setSelected(!outputToInput)
         changeOutputTo.setEnabled(!outputToInput)
         outputToText.text = output
@@ -128,7 +136,7 @@
     }
 
     /* so we can present a list of strings that is always sorted */
-    private class WhiteListModel(basedOn: Collection<String>): ListModel<String> {
+    protected class WhiteListModel(basedOn: Collection<String>): ListModel<String> {
         private val storage = ArrayList<String>(basedOn).apply { sort() }
         private val listeners = mutableListOf<ListDataListener>()
 
@@ -140,50 +148,46 @@
                 index = -(index + 1)
             }
             storage.add(index, newItem)
-            val event = ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, index, index)
-            listeners.forEach { it.intervalAdded(event) }
+            notifyAll(ListDataEvent.INTERVAL_ADDED, index, index)
         }
 
         fun removeAt(index: Int): Unit {
-            if (storage.removeAt(index)) {
-                val event = ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, index, index)
-                listeners.forEach { it.intervalRemoved(event) }
-            }
+            storage.removeAt(index)
+            notifyAll(ListDataEvent.INTERVAL_REMOVED, index, index)
         }
 
         fun remove(oldItem: String): Unit {
-            val index = basedOn.binarySearch(oldItem)
+            val index: Int = storage.binarySearch(oldItem)
             if (index < 0) {
                 return
             }
-            var start = index
-            while (start > 0 && storage[start] == oldItem) {
-                start -= 1
-            }
-            var end = index
-            var max = storage.size - 1
-            while (end < max && storage[end] == oldItem) {
-                end += 1
-            }
-            storage.removeRange(start, end+1)
-            val event = ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, start, end)
-            listeners.forEach { it.intervalRemoved(event) }
+            storage.removeAt(index)
+            notifyAll(ListDataEvent.INTERVAL_REMOVED, index, index)
         }
 
         fun reset(basedOn: Collection<String>): Unit {
-            val removeEvent = ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, 0, storage.size)
+            val oldSize = storage.size
             storage.clear()
+            notifyAll(ListDataEvent.INTERVAL_REMOVED, 0, oldSize)
             storage.addAll(basedOn)
             storage.sort()
-            val addEvent = ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, 0, storage.size)
-            listeners.forEach {
-                it.contentsChanged(removeEvent)
-                it.contentsChanged(addEvent)
+            notifyAll(ListDataEvent.INTERVAL_ADDED, 0, storage.size)
+        }
+
+        /* misc. */
+
+        fun toList(): List<String> = storage
+
+        private fun notifyAll(eType: Int, index0: Int, index1: Int): Unit {
+            val event = ListDataEvent(this, eType, index0, index1)
+            when (eType) {
+                ListDataEvent.CONTENTS_CHANGED -> listeners.forEach { it.contentsChanged(event) }
+                ListDataEvent.INTERVAL_ADDED -> listeners.forEach { it.intervalAdded(event) }
+                ListDataEvent.INTERVAL_REMOVED -> listeners.forEach { it.intervalRemoved(event) }
+                else -> throw RuntimeException("unexpected event type!")
             }
         }
 
-        fun toList(): List<String> = storage
-
         /* so we are a proper ListModel */
 
         override fun addListDataListener(l: ListDataListener): Unit {
@@ -199,30 +203,32 @@
         override fun getSize(): Int = storage.size
     }
 
-    private class WLAddDialog(parent: SettingsDialog): JDialog(parent) {
-        JTextField text = JTextField(40).apply {
+    protected class WLAddDialog(parent: SettingsDialog): JDialog(parent) {
+        private val BW = parent.BW
+        private val BW2 = parent.BW2
+
+        private val toAdd = JTextField(40).apply {
             alignmentX = CENTER_ALIGNMENT
             border = BorderFactory.createEmptyBorder(BW, BW, BW, BW)
         }
 
-        JButton cancelButton = JButton("Cancel").apply {
+        private val cancelButton = JButton("Cancel").apply {
             addActionListener(ActionListener {
-                text.text = ""
+                toAdd.text = ""
                 setVisible(false)
             })
         }
 
-        JButton addButton = JButton("Add").apply {
+        private val addButton = JButton("Add").apply {
             addActionListener(ActionListener {
-                val newItem = text.text?.trim()
+                val newItem = toAdd.text?.trim()
                 if (newItem.isNullOrEmpty()) {
                     Toolkit.getDefaultToolkit().beep()
                 } else {
-                    wlSelectorModel.add(newItem)
+                    parent.wlSelectorModel.add(newItem)
                 }
-                text.text = ""
+                toAdd.text = ""
                 setVisible(false)
-                }
             })
         }
 
@@ -230,7 +236,7 @@
             title = "Add Item to Whitelist"
             contentPane.apply {
                 layout = BoxLayout(this, BoxLayout.Y_AXIS)
-                add(text)
+                add(toAdd)
                 add(Box(BoxLayout.X_AXIS).apply {
                     alignmentX = CENTER_ALIGNMENT
                     border = BorderFactory.createEmptyBorder(BW, BW, BW, BW)
@@ -247,33 +253,38 @@
     }
 
     /* the JList that holds our whitelist */
-    private val wlSelectorModel = WhiteListModel(whitelist.toList())
-    private val wlSelector = JList().apply {
+    protected val wlSelectorModel = WhiteListModel(whitelist.toList())
+    protected val wlSelector: JList<String> = JList<String>().apply {
         visibleRowCount = -1
         model = wlSelectorModel
         clearSelection()
         addListSelectionListener(ListSelectionListener {
             wlDeleteButton.setEnabled(!isSelectionEmpty())
-        }
+        })
     }
 
     /* buttons for managing the whitelist */
-    private val wlAddButton = JButton("Add").apply {
+    protected val wlAddButton = JButton("Add").apply {
         addActionListener(ActionListener { wlAddDialog.setVisible(true) })
     }
-    private val wlDeleteButton = JButton("Delete").apply {
+    protected val wlDeleteButton = JButton("Delete").apply {
         addActionListener(ActionListener {
             wlSelector.selectedIndices.forEach { wlSelectorModel.removeAt(it) }
+            setEnabled(false)
         })
         setEnabled(false)
     }
 
     /* the dialog that the Add button pops up */
-    private val wlAddDialog = WLAddDialog(this)
+    protected val wlAddDialog = WLAddDialog(this)
 
     init {
+        val home = System.getProperty("user.dir")
         if (_outputTo.isNullOrEmpty()) {
-            _outputTo = System.getProperty("user.dir")
+            _outputTo = home
+        }
+        if (_dOutputTo.isNullOrEmpty()) {
+            _dOutputTo = home
         }
         title = "Settings"
         contentPane.apply {