diff --git a/gui/griffon-app/conf/Config.groovy b/gui/griffon-app/conf/Config.groovy index f02f4f62..a0257cde 100644 --- a/gui/griffon-app/conf/Config.groovy +++ b/gui/griffon-app/conf/Config.groovy @@ -66,4 +66,9 @@ mvcGroups { view = 'com.muwire.gui.BrowseView' controller = 'com.muwire.gui.BrowseController' } + 'close-warning' { + model = 'com.muwire.gui.CloseWarningModel' + view = 'com.muwire.gui.CloseWarningView' + controller = 'com.muwire.gui.CloseWarningController' + } } diff --git a/gui/griffon-app/controllers/com/muwire/gui/CloseWarningController.groovy b/gui/griffon-app/controllers/com/muwire/gui/CloseWarningController.groovy new file mode 100644 index 00000000..8ec7d023 --- /dev/null +++ b/gui/griffon-app/controllers/com/muwire/gui/CloseWarningController.groovy @@ -0,0 +1,39 @@ +package com.muwire.gui + +import griffon.core.artifact.GriffonController +import griffon.core.controller.ControllerAction +import griffon.inject.MVCMember +import griffon.metadata.ArtifactProviderFor +import javax.annotation.Nonnull + +@ArtifactProviderFor(GriffonController) +class CloseWarningController { + @MVCMember @Nonnull + CloseWarningModel model + @MVCMember @Nonnull + CloseWarningView view + + UISettings settings + File home + + + void mvcGroupInit(Map args) { + model.closeWarning = settings.closeWarning + } + + @ControllerAction + void close() { + boolean showWarning = !view.checkbox.model.isSelected() + model.closeWarning = showWarning + settings.closeWarning = showWarning + + File props = new File(home, "gui.properties") + props.withOutputStream { + settings.write(it) + } + + view.dialog.setVisible(false) + view.mainFrame.setVisible(false) + mvcGroup.destroy() + } +} \ No newline at end of file diff --git a/gui/griffon-app/models/com/muwire/gui/CloseWarningModel.groovy b/gui/griffon-app/models/com/muwire/gui/CloseWarningModel.groovy new file mode 100644 index 00000000..1f1e6c13 --- /dev/null +++ b/gui/griffon-app/models/com/muwire/gui/CloseWarningModel.groovy @@ -0,0 +1,15 @@ +package com.muwire.gui + +import javax.annotation.Nonnull + +import griffon.core.artifact.GriffonController +import griffon.core.artifact.GriffonModel +import griffon.core.controller.ControllerAction +import griffon.inject.MVCMember +import griffon.metadata.ArtifactProviderFor +import javax.annotation.Nonnull + +@ArtifactProviderFor(GriffonModel) +class CloseWarningModel { + @griffon.transform.Observable boolean closeWarning +} \ No newline at end of file diff --git a/gui/griffon-app/views/com/muwire/gui/CloseWarningView.groovy b/gui/griffon-app/views/com/muwire/gui/CloseWarningView.groovy new file mode 100644 index 00000000..5e506a47 --- /dev/null +++ b/gui/griffon-app/views/com/muwire/gui/CloseWarningView.groovy @@ -0,0 +1,58 @@ +package com.muwire.gui + +import griffon.core.artifact.GriffonView +import griffon.inject.MVCMember +import griffon.metadata.ArtifactProviderFor + +import javax.swing.JDialog +import javax.swing.SwingConstants + +import java.awt.GridBagConstraints +import java.awt.event.WindowAdapter +import java.awt.event.WindowEvent + +import javax.annotation.Nonnull + +@ArtifactProviderFor(GriffonView) +class CloseWarningView { + @MVCMember @Nonnull + FactoryBuilderSupport builder + @MVCMember @Nonnull + CloseWarningModel model + + def mainFrame + def dialog + def panel + def checkbox + + void initUI() { + mainFrame = application.windowManager.findWindow("main-frame") + + dialog = new JDialog(mainFrame, "MuWire will continue running", true) + panel = builder.panel { + gridBagLayout() + label(text : "MuWire will continue running. You can close it from the system tray", constraints : gbc(gridx: 0, gridy: 0, gridwidth : 2)) + label(text : "\n", constraints : gbc(gridx : 0, gridy : 1)) // TODO: real padding + label(text : "Do not show this warning again", constraints : gbc(gridx: 0, gridy : 2, weightx: 100, anchor : GridBagConstraints.LINE_END)) + checkbox = checkBox(selected : bind {model.closeWarning}, constraints : gbc(gridx: 1, gridy :2)) + panel (constraints : gbc(gridx: 0, gridy : 3, gridwidth : 2)) { + button(text : "Ok", closeAction) + } + } + dialog.getContentPane().add(panel) + dialog.pack() + dialog.setResizable(false) + dialog.setLocationRelativeTo(mainFrame) + dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE) + dialog.addWindowListener(new WindowAdapter() { + public void windowClosed(WindowEvent e) { + mainFrame.setVisible(false) + mvcGroup.destroy() + } + }) + } + + void mvcGroupInit(Map args) { + dialog.show() + } +} \ No newline at end of file diff --git a/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy b/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy index 76d6ffe4..b8bd4063 100644 --- a/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy +++ b/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy @@ -21,6 +21,7 @@ import javax.swing.JTable import javax.swing.JTree import javax.swing.ListSelectionModel import javax.swing.SwingConstants +import javax.swing.SwingUtilities import javax.swing.TransferHandler import javax.swing.border.Border import javax.swing.table.DefaultTableCellRenderer @@ -74,7 +75,7 @@ class MainFrameView { builder.with { application(size : [1024,768], id: 'main-frame', locationRelativeTo : null, - defaultCloseOperation : JFrame.HIDE_ON_CLOSE, + defaultCloseOperation : JFrame.DO_NOTHING_ON_CLOSE, title: application.configuration['application.title'] + " " + metadata["application.version"] + " revision " + metadata["build.revision"], iconImage: imageIcon('/MuWire-48x48.png').image, @@ -440,22 +441,31 @@ class MainFrameView { } }) - if (!application.getContext().get("tray-icon")) { - mainFrame.addWindowListener(new WindowAdapter(){ - public void windowClosing(WindowEvent e) { - application.getWindowManager().findWindow("shutdown-window").setVisible(true) - Core core = application.getContext().get("core") - if (core != null) { - Thread t = new Thread({ - core.shutdown() - application.shutdown() - }as Runnable) - t.start() - } - } - }) - } - + mainFrame.addWindowListener(new WindowAdapter(){ + public void windowClosing(WindowEvent e) { + if (application.getContext().get("tray-icon")) { + if (settings.closeWarning) { + runInsideUIAsync { + Map args2 = new HashMap<>() + args2.put("settings", settings) + args2.put("home", model.core.home) + mvcGroup.createMVCGroup("close-warning", "Close Warning", args2) + } + } + } else { + mainFrame.setVisible(false) + application.getWindowManager().findWindow("shutdown-window").setVisible(true) + Core core = application.getContext().get("core") + if (core != null) { + Thread t = new Thread({ + core.shutdown() + application.shutdown() + }as Runnable) + t.start() + } + } + }}) + def downloadsTable = builder.getVariable("downloads-table") def selectionModel = downloadsTable.getSelectionModel() selectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION) diff --git a/gui/src/main/groovy/com/muwire/gui/UISettings.groovy b/gui/src/main/groovy/com/muwire/gui/UISettings.groovy index f80f9e1c..63016356 100644 --- a/gui/src/main/groovy/com/muwire/gui/UISettings.groovy +++ b/gui/src/main/groovy/com/muwire/gui/UISettings.groovy @@ -11,6 +11,7 @@ class UISettings { boolean clearFinishedDownloads boolean excludeLocalResult boolean showSearchHashes + boolean closeWarning UISettings(Properties props) { lnf = props.getProperty("lnf", "system") @@ -22,6 +23,7 @@ class UISettings { showSearchHashes = Boolean.parseBoolean(props.getProperty("showSearchHashes","true")) autoFontSize = Boolean.parseBoolean(props.getProperty("autoFontSize","false")) fontSize = Integer.parseInt(props.getProperty("fontSize","12")) + closeWarning = Boolean.parseBoolean(props.getProperty("closeWarning","true")) } void write(OutputStream out) throws IOException { @@ -34,6 +36,7 @@ class UISettings { props.setProperty("showSearchHashes", String.valueOf(showSearchHashes)) props.setProperty("autoFontSize", String.valueOf(autoFontSize)) props.setProperty("fontSize", String.valueOf(fontSize)) + props.setProperty("closeWarning", String.valueOf(closeWarning)) if (font != null) props.setProperty("font", font)