diff src/name/blackcap/clipman/Main.kt @ 47:19d9da731c43

Recoded; cleaned up root namespace, removed race conditions.
author David Barts <n5jrn@me.com>
date Sun, 12 Apr 2020 14:31:06 -0700
parents 339e2da5bf83
children 7a75c743f973
line wrap: on
line diff
--- a/src/name/blackcap/clipman/Main.kt	Mon Feb 10 16:40:09 2020 -0700
+++ b/src/name/blackcap/clipman/Main.kt	Sun Apr 12 14:31:06 2020 -0700
@@ -35,10 +35,6 @@
 val MONO_SIZE = 14
 val PROP_SIZE = 16
 
-/* the queue of data we deal with and the main application frame */
-val queue = LateInit<PasteboardQueue>()
-val frame = LateInit<JFrame>()
-
 /* kills the updating thread (and does a system exit) when needed */
 class KillIt() : WindowListener {
     // events we don't care about
@@ -91,7 +87,7 @@
                         })
                     }
                     piv.searchable.addMouseListener(this)
-                    queue.v.add(QueueItem(contents, piv))
+                    Application.queue.add(QueueItem(contents, piv))
                     oldContents = contents
                 }
             }
@@ -131,15 +127,15 @@
         if (source == null) {
             return
         }
-        queue.v.deselectAll()
+        Application.queue.deselectAll()
         source.selected = true
         source.validate()
-        anyRequired.enable()
+        Application.anyRequired.enable()
         source.basedOn.let {
             if (it is PasteboardItem.HTML || it is PasteboardItem.RTF) {
-                styledRequired.enable()
+                Application.styledRequired.enable()
             } else {
-                styledRequired.disable()
+                Application.styledRequired.disable()
             }
         }
     }
@@ -154,7 +150,7 @@
 
  	private fun maybeShowPopup(e: MouseEvent) {
  	    if (e.isPopupTrigger()) {
- 	        popupMenu.show(e.component, e.x, e.y)
+ 	        Application.popupMenu.show(e.component, e.x, e.y)
  	    }
  	}
 
@@ -162,36 +158,70 @@
  	override fun mouseExited(e: MouseEvent) { }
 }
 
+object Application {
+    /* name we call ourselves */
+    val MYNAME = "ExifWasher"
+
+    /* global UI objects, must be created on the Swing thread */
+    var queue: PasteboardQueue by setOnce()
+    var frame: JFrame by setOnce()
+    var coerceDialog: CoerceDialog by setOnce()
+    var menuItemListener: MenuItemListener by setOnce()
+    var popupMenu: MyPopupMenu by setOnce()
+    var searchDialog: SearchDialog by setOnce()
+    var settingsDialog: SettingsDialog by setOnce()
+
+    /* used by the menus, but not themselves Swing objects */
+    val anyRequired = SelectionRequired()
+    val styledRequired = SelectionRequired()
+
+    fun initialize() {
+        /* make ourselves look more native */
+        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+
+        /* initialize reusable GUI objects */
+        frame = JFrame(MYNAME)  /* must init this gui object first */
+        coerceDialog = CoerceDialog()
+        menuItemListener = MenuItemListener() /* must init before menus */
+        popupMenu = MyPopupMenu()
+        searchDialog = SearchDialog()
+        settingsDialog = SettingsDialog()
+
+        /* set up the main frame */
+        val con = JPanel().apply {
+            layout = BoxLayout(this, BoxLayout.Y_AXIS)
+            border = BorderFactory.createEmptyBorder(PANEL_BORDER, PANEL_BORDER, PANEL_BORDER, PANEL_BORDER)
+            background = frame.background
+        }
+        frame.apply {
+            jMenuBar = MyMenuBar()
+            contentPane.add(
+                JScrollPane(con).apply {
+                    verticalScrollBarPolicy = ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS
+                    horizontalScrollBarPolicy = ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER
+                    preferredSize = Dimension(CPWIDTH, CPHEIGHT)
+                    background = frame.background
+                }, BorderLayout.CENTER)
+            pack()
+            setVisible(true)
+            addWindowListener(KillIt())
+        }
+        setMacMenus()
+
+        /* launch the updating thread */
+        queue = PasteboardQueue(con, settingsDialog.qLength)
+        UpdateIt(1000).apply { start() }
+    }
+}
+
+
 /* entry point */
 fun main(args: Array<String>) {
     LOGGER.log(Level.INFO, "beginning execution")
     if (OS.type == OS.MAC) {
         System.setProperty("apple.laf.useScreenMenuBar", "true")
     }
-    lateinit var con: JPanel
-    inSynSwingThread {
-        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
-        frame.v = JFrame(MYNAME)
-        con = JPanel().apply {
-            layout = BoxLayout(this, BoxLayout.Y_AXIS)
-            border = BorderFactory.createEmptyBorder(PANEL_BORDER, PANEL_BORDER, PANEL_BORDER, PANEL_BORDER)
-            background = frame.v.background
-        }
-        frame.v.jMenuBar = menuBar
-        frame.v.apply {
-            contentPane.add(
-                JScrollPane(con).apply {
-                    verticalScrollBarPolicy = ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS
-                    horizontalScrollBarPolicy = ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER
-                    preferredSize = Dimension(CPWIDTH, CPHEIGHT)
-                    background = frame.v.background
-                }, BorderLayout.CENTER)
-            pack()
-            setVisible(true)
-            addWindowListener(KillIt())
-        }
-        setMacMenus()
+    inSwingThread {
+        Application.initialize()
     }
-    queue.v = PasteboardQueue(con, settingsDialog.qLength)
-    UpdateIt(1000).apply { start() }
 }