mirror of https://github.com/zlatinb/muwire
skeleton of setup wizard
parent
bf28278f72
commit
c041f6baaa
|
@ -141,4 +141,9 @@ mvcGroups {
|
||||||
view = 'com.muwire.gui.SignView'
|
view = 'com.muwire.gui.SignView'
|
||||||
controller = 'com.muwire.gui.SignController'
|
controller = 'com.muwire.gui.SignController'
|
||||||
}
|
}
|
||||||
|
'wizard' {
|
||||||
|
model = 'com.muwire.gui.wizard.WizardModel'
|
||||||
|
view = 'com.muwire.gui.wizard.WizardView'
|
||||||
|
controller = 'com.muwire.gui.wizard.WizardController'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package com.muwire.gui.wizard
|
||||||
|
|
||||||
|
import griffon.core.artifact.GriffonController
|
||||||
|
import griffon.core.controller.ControllerAction
|
||||||
|
import griffon.inject.MVCMember
|
||||||
|
import griffon.metadata.ArtifactProviderFor
|
||||||
|
import javax.annotation.Nonnull
|
||||||
|
import javax.swing.JOptionPane
|
||||||
|
|
||||||
|
@ArtifactProviderFor(GriffonController)
|
||||||
|
class WizardController {
|
||||||
|
@MVCMember @Nonnull
|
||||||
|
WizardModel model
|
||||||
|
@MVCMember @Nonnull
|
||||||
|
WizardView view
|
||||||
|
|
||||||
|
@ControllerAction
|
||||||
|
void previous() {
|
||||||
|
model.currentStep--
|
||||||
|
recalcButtons()
|
||||||
|
view.updateLayout()
|
||||||
|
}
|
||||||
|
|
||||||
|
@ControllerAction
|
||||||
|
void next() {
|
||||||
|
def errors = model.steps[model.currentStep].validate()
|
||||||
|
if (errors) {
|
||||||
|
String errorMessage = String.join("\n", errors)
|
||||||
|
JOptionPane.showMessageDialog(model.parent, errorMessage, "Invalid Input", JOptionPane.ERROR_MESSAGE)
|
||||||
|
} else {
|
||||||
|
model.currentStep++
|
||||||
|
recalcButtons()
|
||||||
|
view.updateLayout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ControllerAction
|
||||||
|
void finish() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void recalcButtons() {
|
||||||
|
model.previousButtonEnabled = model.currentStep > 0
|
||||||
|
model.nextButtonEnabled = model.steps.size() > (model.currentStep + 1)
|
||||||
|
model.finishButtonEnabled = model.steps.size() == (model.currentStep + 1)
|
||||||
|
}
|
||||||
|
}
|
|
@ -54,27 +54,41 @@ class Ready extends AbstractLifecycleHandler {
|
||||||
} else {
|
} else {
|
||||||
log.info("creating new properties")
|
log.info("creating new properties")
|
||||||
props = new MuWireSettings()
|
props = new MuWireSettings()
|
||||||
props.incompleteLocation = new File(home, "incompletes")
|
boolean embeddedRouterAvailable = Boolean.parseBoolean(System.getProperties().getProperty("embeddedRouter"))
|
||||||
props.embeddedRouter = Boolean.parseBoolean(System.getProperties().getProperty("embeddedRouter"))
|
|
||||||
props.updateType = System.getProperty("updateType","jar")
|
def parent = application.windowManager.findWindow("event-list")
|
||||||
props.setNickname(selectNickname())
|
Properties i2pProps = new Properties()
|
||||||
|
|
||||||
|
def params = [:]
|
||||||
|
params['parent'] = parent
|
||||||
|
params['embeddedRouterAvailable'] = embeddedRouterAvailable
|
||||||
|
params['muSettings'] = props
|
||||||
|
params['i2pProps'] = i2pProps
|
||||||
|
|
||||||
|
application.mvcGroupManager.createMVCGroup("wizard", params)
|
||||||
|
|
||||||
|
|
||||||
def portableDownloads = System.getProperty("portable.downloads")
|
// props.incompleteLocation = new File(home, "incompletes")
|
||||||
if (portableDownloads != null) {
|
// props.embeddedRouter = Boolean.parseBoolean(System.getProperties().getProperty("embeddedRouter"))
|
||||||
props.downloadLocation = new File(portableDownloads)
|
// props.updateType = System.getProperty("updateType","jar")
|
||||||
} else {
|
// props.setNickname(selectNickname())
|
||||||
def chooser = new JFileChooser()
|
//
|
||||||
chooser.setFileHidingEnabled(false)
|
//
|
||||||
chooser.setDialogTitle("Select a directory where downloads will be saved")
|
// def portableDownloads = System.getProperty("portable.downloads")
|
||||||
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)
|
// if (portableDownloads != null) {
|
||||||
int rv = chooser.showOpenDialog(null)
|
// props.downloadLocation = new File(portableDownloads)
|
||||||
if (rv != JFileChooser.APPROVE_OPTION) {
|
// } else {
|
||||||
JOptionPane.showMessageDialog(null, "MuWire will now exit")
|
// def chooser = new JFileChooser()
|
||||||
System.exit(0)
|
// chooser.setFileHidingEnabled(false)
|
||||||
}
|
// chooser.setDialogTitle("Select a directory where downloads will be saved")
|
||||||
props.downloadLocation = chooser.getSelectedFile()
|
// chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)
|
||||||
}
|
// int rv = chooser.showOpenDialog(null)
|
||||||
|
// if (rv != JFileChooser.APPROVE_OPTION) {
|
||||||
|
// JOptionPane.showMessageDialog(null, "MuWire will now exit")
|
||||||
|
// System.exit(0)
|
||||||
|
// }
|
||||||
|
// props.downloadLocation = chooser.getSelectedFile()
|
||||||
|
// }
|
||||||
|
|
||||||
propsFile.withPrintWriter("UTF-8", {
|
propsFile.withPrintWriter("UTF-8", {
|
||||||
props.write(it)
|
props.write(it)
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.muwire.gui.wizard
|
||||||
|
|
||||||
|
import java.awt.Component
|
||||||
|
|
||||||
|
import com.muwire.core.MuWireSettings
|
||||||
|
|
||||||
|
import griffon.core.artifact.GriffonModel
|
||||||
|
import griffon.transform.Observable
|
||||||
|
import griffon.metadata.ArtifactProviderFor
|
||||||
|
|
||||||
|
@ArtifactProviderFor(GriffonModel)
|
||||||
|
class WizardModel {
|
||||||
|
Component parent
|
||||||
|
boolean embeddedRouterAvailable
|
||||||
|
MuWireSettings muSettings
|
||||||
|
Properties i2pProps
|
||||||
|
|
||||||
|
final List<WizardStep> steps = [new NicknameStep(),
|
||||||
|
new DirectoriesStep()]
|
||||||
|
int currentStep
|
||||||
|
|
||||||
|
@Observable boolean finishButtonEnabled
|
||||||
|
@Observable boolean previousButtonEnabled
|
||||||
|
@Observable boolean nextButtonEnabled
|
||||||
|
|
||||||
|
void mvcGroupInit(Map<String,String> args) {
|
||||||
|
currentStep = 0
|
||||||
|
previousButtonEnabled = false
|
||||||
|
nextButtonEnabled = steps.size() > (currentStep + 1)
|
||||||
|
finishButtonEnabled = steps.size() == currentStep + 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.muwire.gui.wizard
|
||||||
|
|
||||||
|
import griffon.core.artifact.GriffonView
|
||||||
|
import griffon.inject.MVCMember
|
||||||
|
import griffon.metadata.ArtifactProviderFor
|
||||||
|
|
||||||
|
import javax.swing.JDialog
|
||||||
|
import javax.swing.SwingConstants
|
||||||
|
|
||||||
|
import java.awt.BorderLayout
|
||||||
|
import java.awt.event.WindowAdapter
|
||||||
|
import java.awt.event.WindowEvent
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull
|
||||||
|
|
||||||
|
@ArtifactProviderFor(GriffonView)
|
||||||
|
class WizardView {
|
||||||
|
@MVCMember @Nonnull
|
||||||
|
FactoryBuilderSupport builder
|
||||||
|
@MVCMember @Nonnull
|
||||||
|
WizardModel model
|
||||||
|
|
||||||
|
def dialog
|
||||||
|
def p
|
||||||
|
|
||||||
|
void initUI() {
|
||||||
|
dialog = new JDialog(model.parent, "Setup Wizard", true)
|
||||||
|
|
||||||
|
p = builder.panel {
|
||||||
|
borderLayout()
|
||||||
|
panel (id : "cards-panel", constraints : BorderLayout.CENTER) {
|
||||||
|
cardLayout()
|
||||||
|
model.steps.each {
|
||||||
|
it.buildUI(builder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panel (constraints : BorderLayout.SOUTH) {
|
||||||
|
button(text : "Previous", enabled : bind {model.previousButtonEnabled}, previousAction)
|
||||||
|
button(text : "Next", enabled : bind {model.nextButtonEnabled}, nextAction)
|
||||||
|
button(text : "Finish", enabled : bind {model.finishButtonEnabled}, finishAction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateLayout() {
|
||||||
|
String constraints = model.steps[model.currentStep].getConstraint()
|
||||||
|
def cardsPanel = builder.getVariable("cards-panel")
|
||||||
|
cardsPanel.getLayout().show(cardsPanel, constraints)
|
||||||
|
}
|
||||||
|
|
||||||
|
void mvcGroupInit(Map<String,String> args) {
|
||||||
|
dialog.getContentPane().add(p)
|
||||||
|
dialog.pack()
|
||||||
|
dialog.setLocationRelativeTo(model.parent)
|
||||||
|
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE)
|
||||||
|
dialog.addWindowListener( new WindowAdapter() {
|
||||||
|
public void windowClosed(WindowEvent e) {
|
||||||
|
mvcGroup.destroy()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
dialog.show()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
package com.muwire.gui.wizard
|
||||||
|
|
||||||
|
import javax.swing.JFileChooser
|
||||||
|
|
||||||
|
import com.muwire.core.MuWireSettings
|
||||||
|
|
||||||
|
class DirectoriesStep extends WizardStep {
|
||||||
|
|
||||||
|
def downloadLocationField
|
||||||
|
def incompleteLocationField
|
||||||
|
def downloadLocationButton
|
||||||
|
def incompleteLocationButton
|
||||||
|
|
||||||
|
public DirectoriesStep(String constraint) {
|
||||||
|
super("directories")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void buildUI(FactoryBuilderSupport builder) {
|
||||||
|
File defaultDownloadLocation = new File(System.getProperty("user.home"), "MuWire Downloads")
|
||||||
|
File defaultIncompleteLocation = new File(System.getProperty("user.home"), "MuWire Incompletes")
|
||||||
|
|
||||||
|
builder.panel(constraints : getConstraint()) {
|
||||||
|
gridBagLayout()
|
||||||
|
label(text : "Select directories for saving downloaded and incomplete files. They will be created if they do not already exist",
|
||||||
|
constraints : gbc(gridx: 0, gridy: 0, gridwidth : 2))
|
||||||
|
|
||||||
|
label(text : "Directory for saving downloaded files", constraints : gbc(gridx:0, gridy: 1))
|
||||||
|
downloadLocationField = textField(text : defaultDownloadLocation.getAbsolutePath(), constraints : gbc(gridx : 0, gridy : 2))
|
||||||
|
downloadLocationButton = button(text : "Choose", constraints : gbc(gridx: 1, gridy: 2), actionPerformed : showDownloadChooser)
|
||||||
|
label(text : "Directory for storing incomplete files", constraints : gbc(gridx:0, gridy: 3))
|
||||||
|
incompleteLocationField = textField(text : defaultIncompleteLocation.getAbsolutePath(), constraints : gbc(gridx:0, gridy:4))
|
||||||
|
incompleteLocationButton = button(text : "Choose", constraints : gbc(gridx: 1, gridy: 4), actionPerformed : showIncompleteChooser)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<String> validate() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void apply(MuWireSettings muSettings, Properties i2pSettings) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
def showDownloadChooser = {
|
||||||
|
String text = chooseFile("Select directory for downloaded files")
|
||||||
|
if (text != null)
|
||||||
|
downloadLocationField.text = text
|
||||||
|
}
|
||||||
|
|
||||||
|
def showIncompleteChooser = {
|
||||||
|
String text = chooseFile("Select directory for incomplete files")
|
||||||
|
if (text != null)
|
||||||
|
incompleteLocationField.text = text
|
||||||
|
}
|
||||||
|
|
||||||
|
private String chooseFile(String title) {
|
||||||
|
def chooser = new JFileChooser()
|
||||||
|
chooser.setFileHidingEnabled(false)
|
||||||
|
chooser.setDialogTitle(title)
|
||||||
|
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)
|
||||||
|
int rv = chooser.showOpenDialog(null)
|
||||||
|
if (rv == JFileChooser.APPROVE_OPTION)
|
||||||
|
return chooser.getSelectedFile().getAbsolutePath()
|
||||||
|
else
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.muwire.gui.wizard
|
||||||
|
|
||||||
|
import com.muwire.core.Constants
|
||||||
|
import com.muwire.core.MuWireSettings
|
||||||
|
import com.muwire.core.util.DataUtil
|
||||||
|
|
||||||
|
class NicknameStep extends WizardStep {
|
||||||
|
|
||||||
|
volatile def nickField
|
||||||
|
|
||||||
|
public NicknameStep() {
|
||||||
|
super("nickname")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void buildUI(FactoryBuilderSupport builder) {
|
||||||
|
builder.panel(constraints : getConstraint()) {
|
||||||
|
label(text: "Select a nickname")
|
||||||
|
nickField = textField(columns: 30)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<String> validate() {
|
||||||
|
if (!DataUtil.isValidName(nickField.text))
|
||||||
|
return ["Nickname cannot contain any of ${Constants.INVALID_NICKNAME_CHARS} and must be no longer than ${Constants.MAX_NICKNAME_LENGTH} characters. Choose another."]
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void apply(MuWireSettings muSettings, Properties i2pSettings) {
|
||||||
|
muSettings.nickname = nickField.text
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.muwire.gui.wizard
|
||||||
|
|
||||||
|
import com.muwire.core.MuWireSettings
|
||||||
|
|
||||||
|
abstract class WizardStep {
|
||||||
|
|
||||||
|
final String constraint
|
||||||
|
|
||||||
|
protected WizardStep(String constraint) {
|
||||||
|
this.constraint = constraint
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected abstract void buildUI(FactoryBuilderSupport builder)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list of errors, null if validation is successful
|
||||||
|
*/
|
||||||
|
protected abstract List<String> validate()
|
||||||
|
|
||||||
|
protected abstract void apply(MuWireSettings muSettings, Properties i2pSettings)
|
||||||
|
}
|
Loading…
Reference in New Issue