From 223fe1f136d2c167993921bec10dc0b648e7ea29 Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Fri, 23 Oct 2015 13:44:11 +0000 Subject: [PATCH] Added NewProjectDialog, fixed some error handling and general stability fixes --- src/com/coder/client/CoderClient.java | 208 +++++++++++++++--- src/com/coder/client/Session.java | 10 +- src/com/coder/client/gui/GuiWindow.java | 15 +- .../coder/client/gui/editor/EditorWindow.java | 13 ++ .../gui/editor/EditorWindowListener.java | 1 + .../coder/client/gui/login/LoginDialog.java | 1 + .../gui/newProject/NewProjectDialog.fxml | 13 ++ .../gui/newProject/NewProjectDialog.java | 82 +++++++ .../newProject/NewProjectDialogListener.java | 11 + .../selectProject/SelectProjectDialog.fxml | 9 +- .../selectProject/SelectProjectDialog.java | 9 + .../gui/selectServer/SelectServerDialog.fxml | 10 +- .../gui/selectServer/SelectServerDialog.java | 8 + 13 files changed, 336 insertions(+), 54 deletions(-) create mode 100644 src/com/coder/client/gui/newProject/NewProjectDialog.fxml create mode 100644 src/com/coder/client/gui/newProject/NewProjectDialog.java create mode 100644 src/com/coder/client/gui/newProject/NewProjectDialogListener.java diff --git a/src/com/coder/client/CoderClient.java b/src/com/coder/client/CoderClient.java index 17a65a6..4680f0a 100644 --- a/src/com/coder/client/CoderClient.java +++ b/src/com/coder/client/CoderClient.java @@ -6,10 +6,13 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.coder.client.Session; +import com.coder.client.gui.GuiWindow; import com.coder.client.gui.editor.EditorWindow; import com.coder.client.gui.editor.EditorWindowListener; import com.coder.client.gui.login.LoginDialog; import com.coder.client.gui.login.LoginDialogListener; +import com.coder.client.gui.newProject.NewProjectDialog; +import com.coder.client.gui.newProject.NewProjectDialogListener; import com.coder.client.gui.selectProject.SelectProjectDialog; import com.coder.client.gui.selectProject.SelectProjectDialogListener; import com.coder.client.gui.selectServer.SelectServerDialog; @@ -17,9 +20,12 @@ import com.coder.client.gui.selectServer.SelectServerDialogListener; import com.coder.server.CoderServer; import com.coder.server.message.CoderMessage; import com.coder.server.message.ConfigData; +import com.coder.server.message.ProjectCreateReqMsg; import com.coder.server.message.ProjectListData; import com.coder.server.message.ProjectListReqMsg; +import com.coder.server.message.ProjectReqMsg; import com.coder.server.message.ProjectRspMsg; +import com.coder.server.message.ProjectTypeReqMsg; import zutil.log.CompactLogFormatter; import zutil.log.LogUtil; @@ -41,14 +47,15 @@ public class CoderClient extends Application{ private LoginDialog loginDialog; private SelectProjectDialog selectProjectDialog; private SelectServerDialog selectServerDialog; + private NewProjectDialog newProjectDialog; //state variables private String serverURL = null; private int serverPort = CoderServer.SERVER_PORT; private String username = null; private char[] password = null; //should only be anything else than null if defined by program argument - private String loginErrorMessage = ""; private String project = null; + private GuiWindow projectSelectionWindow = null; //points to the GUI that selected a project for the editor. If any error occurs while creating/loading the project, this is the window we will go back to. //services SSDPClient ssdpClient; @@ -96,6 +103,7 @@ public class CoderClient extends Application{ setupLoginDialog(); setupSelectProjectDialog(); setupEditWindow(); + setupNewProjectDialog(); }catch(IOException e){ logger.log(Level.SEVERE, "could not load all GUI elements", e); System.exit(1); @@ -111,7 +119,7 @@ public class CoderClient extends Application{ //start program logic selectServerDialog.showOnStage(mainStage); - + } private void setupSelectServerDialog() throws IOException{ @@ -120,9 +128,9 @@ public class CoderClient extends Application{ @Override public void willShow() { closeCurrentSession(); - ssdpClient.clearServices(); selectServerDialog.clearServerList(); if(ssdpClient != null){ + ssdpClient.clearServices(); ssdpClient.requestService("coder:discover"); }else{ logger.severe("could not send a SSDP request since the client is not setup"); @@ -133,11 +141,10 @@ public class CoderClient extends Application{ @Override public void exit() { logger.info("terminating"); - System.exit(0); + Platform.exit(); } @Override public void connect(String address, int port) { - //selectServerDialog.hide(); serverURL = address; serverPort = port; //connect session @@ -146,8 +153,31 @@ public class CoderClient extends Application{ logger.warning("Could not setup a connection to " + serverURL + ":" + port); serverURL = null; serverPort = CoderServer.SERVER_PORT; + selectServerDialog.setErrorMessage("ERROR: Unable to connect to remote host"); selectServerDialog.showOnStage(mainStage); }else{ + selectServerDialog.setErrorMessage(""); + // create a guard for when the session is closed + new Thread(new Runnable(){ + @Override + public void run() { + logger.fine("starting a session guard"); + while(true){ + if(session == null || !session.isConnected()){ + logger.fine("session guard: no connection"); + Platform.runLater(new Runnable() { + @Override + public void run() { + selectServerDialog.setErrorMessage("The current session was disconnected"); + selectServerDialog.showOnStage(mainStage); + } + }); + break; + } + Thread.yield(); + } + logger.fine("terminating session guard"); + }}).start(); loginDialog.showOnStage(mainStage); } } @@ -161,7 +191,6 @@ public class CoderClient extends Application{ public void willShow() { loginDialog.setUsername(username); loginDialog.setPassword(password); - loginDialog.setErrorMessage(loginErrorMessage); } @Override public void cancel() { @@ -178,38 +207,83 @@ public class CoderClient extends Application{ if(!authenticated){ logger.severe("Authentication failed: wrong username or password"); password = null; - loginErrorMessage = "Wrong username or password"; + loginDialog.setErrorMessage("Wrong username or password"); selectServerDialog.showOnStage(mainStage); + return; }else{ - loginErrorMessage = ""; + loginDialog.setErrorMessage(""); setupSessionListener(); //resister a message listener to the session session.start(); //start receiving traffic from the server selectProjectDialog.showOnStage(mainStage); } } - private void setupSessionListener(){ - session.addCoderMessageReceivedListener(new CoderMessageReceivedListener() { - @Override - public void projectListRspReceived(final Map projectListRsp) { - Platform.runLater(new Runnable() { - @Override - public void run() { - for(String projectName : projectListRsp.keySet()){ - ProjectListData projectData = projectListRsp.get(projectName); - selectProjectDialog.addProjectToList(projectName, projectData); - } - } - }); - } - @Override - public void projectRspReceived(ProjectRspMsg projectRspMsg) { - // TODO Auto-generated method stub - } - @Override - public void projectTypeRspReceived(Map projectTypeRsp) { - // TODO Auto-generated method stub - - } + }); + } + + /** + * To be called after a session has been connected and authenticated + */ + private void setupSessionListener(){ + if(session == null){ + logger.warning("Cannot setup session listeners for null instance. ignoring call."); + return; + } + if(!session.isAuthenticated()){ + logger.warning("Cannot setup session listeners for a non-authenticated session. ignoring call."); + return; + } + session.addCoderMessageReceivedListener(new CoderMessageReceivedListener() { + @Override + public void projectListRspReceived(final Map projectListRsp) { + logger.fine("a ProjectListRsp received"); + Platform.runLater(new Runnable() { + @Override + public void run() { + for(String projectName : projectListRsp.keySet()){ + ProjectListData projectData = projectListRsp.get(projectName); + selectProjectDialog.addProjectToList(projectName, projectData); + } + } + }); + } + @Override + public void projectRspReceived(final ProjectRspMsg projectRspMsg) { + logger.fine("a ProjectRspMsg received"); + Platform.runLater(new Runnable() { + @Override + public void run() { + if(projectRspMsg.error != null){ + logger.severe("Server responded on the project request with the following error message: " + projectRspMsg.error); + project = null; + if(projectSelectionWindow != null){ + projectSelectionWindow.setErrorMessage("ERROR: " + projectRspMsg.error); + projectSelectionWindow.showOnStage(mainStage); + return; + }else{ + logger.severe("Undefined error message handler. Unrecoverable state. Terminating"); + Platform.exit(); + return; + } + }else{ + if(projectSelectionWindow != null){ + projectSelectionWindow.setErrorMessage(""); + } + //TODO: handle msg + } + } + }); + } + @Override + public void projectTypeRspReceived(final Map projectTypeRsp) { + logger.fine("a ProjectTypeRspMsg received"); + Platform.runLater(new Runnable() { + @Override + public void run() { + for(String typeName : projectTypeRsp.keySet()){ + ConfigData typeData = projectTypeRsp.get(typeName); + newProjectDialog.addProjectTypeToList(typeName, typeData); + } + } }); } }); @@ -221,20 +295,21 @@ public class CoderClient extends Application{ @Override public void willShow() { selectProjectDialog.clearProjectList(); - if(project == null){ + if(project == null || project.isEmpty()){ sendProjectListReq(); - }else{ - selectProjectDialog.setProject(project); } + selectProjectDialog.setProject(project); } @Override public void open(String selectedProjectName) { + projectSelectionWindow = selectProjectDialog; project = selectedProjectName; editorWindow.showOnStage(mainStage); } @Override public void newProject() { - //TODO + project = null; + newProjectDialog.showOnStage(mainStage); } @Override public void cancel() { @@ -261,12 +336,57 @@ public class CoderClient extends Application{ }); } + private void setupNewProjectDialog() throws IOException { + this.newProjectDialog = new NewProjectDialog(); + this.newProjectDialog.addNewProjectDialogListener(new NewProjectDialogListener(){ + @Override + public void willShow() { + newProjectDialog.clearProjectTypeList(); + sendProjectTypeReqMsg(); + } + @Override + public void create(String newProjectName, String projectType) { + projectSelectionWindow = newProjectDialog; + sendProjectCreateReqMsg(newProjectName, projectType); + project = newProjectName; + editorWindow.showOnStage(mainStage); + } + private void sendProjectTypeReqMsg(){ + CoderMessage msg = new CoderMessage(); + msg.ProjectTypeReq = new ProjectTypeReqMsg(); + try { + session.send(msg); + } catch (IOException e) { + logger.log(Level.SEVERE, "Unable to send ProjectTypeReq", e); + closeCurrentSession(); + } + } + private void sendProjectCreateReqMsg(String projectName, String projectType){ + CoderMessage msg = new CoderMessage(); + msg.ProjectCreateReq = new ProjectCreateReqMsg(); + msg.ProjectCreateReq.name = projectName; + msg.ProjectCreateReq.type = projectType; + try { + session.send(msg); + } catch (IOException e) { + logger.log(Level.SEVERE, "Unable to send ProjectCreateReq", e); + closeCurrentSession(); + } + } + @Override + public void cancel() { + project = null; + selectProjectDialog.showOnStage(mainStage); + } + }); + } + private void setupEditWindow() throws IOException { this.editorWindow = new EditorWindow(); this.editorWindow.addEditorWindowListener(new EditorWindowListener() { @Override public void willShow() { - //TODO + sendProjectReqMsg(); } @Override public void compile() { @@ -276,6 +396,22 @@ public class CoderClient extends Application{ public void run() { //TODO } + private void sendProjectReqMsg(){ + CoderMessage msg = new CoderMessage(); + msg.ProjectReq = new ProjectReqMsg(); + msg.ProjectReq.name = project; + try { + session.send(msg); + } catch (IOException e) { + logger.log(Level.SEVERE, "Unable to send ProjectReqMsg", e); + closeCurrentSession(); + } + } + @Override + public void changeProject() { + project = null; + selectProjectDialog.showOnStage(mainStage); + } }); } diff --git a/src/com/coder/client/Session.java b/src/com/coder/client/Session.java index 2d246d7..4548ca6 100644 --- a/src/com/coder/client/Session.java +++ b/src/com/coder/client/Session.java @@ -20,7 +20,7 @@ public class Session extends Thread { private HashSet messageReceivedlisteners = new HashSet(); - private boolean authenticated; + private boolean authenticated = false; private Socket socket; private JSONObjectInputStream in; private JSONObjectOutputStream out; @@ -35,11 +35,11 @@ public class Session extends Thread { try { session.socket = new Socket(url, port); } catch (UnknownHostException e) { - logger.log(Level.SEVERE, null, e); + logger.log(Level.FINE, null, e); session.close(); return null; } catch (IOException e) { - logger.log(Level.SEVERE, null, e); + logger.log(Level.FINE, null, e); session.close(); return null; } @@ -111,6 +111,10 @@ public class Session extends Thread { return new String[]{}; } + public boolean isAuthenticated(){ + return authenticated; + } + public boolean authenticate(String username, char[] clearTextPassword) { logger.fine("Authenticating session"); diff --git a/src/com/coder/client/gui/GuiWindow.java b/src/com/coder/client/gui/GuiWindow.java index e64faa6..9df10f0 100644 --- a/src/com/coder/client/gui/GuiWindow.java +++ b/src/com/coder/client/gui/GuiWindow.java @@ -8,13 +8,11 @@ import javafx.fxml.FXMLLoader; import javafx.fxml.Initializable; import javafx.scene.Parent; import javafx.scene.Scene; -import javafx.stage.Modality; import javafx.stage.Stage; public abstract class GuiWindow implements Initializable{ private Scene scene; - private Stage stage; /** * constructor @@ -34,16 +32,16 @@ public abstract class GuiWindow implements Initializable{ public void showOnStage(Stage stage){ stage.setScene(scene); stage.setTitle(getTitle()); - this.stage = stage; + //this.stage = stage; willShow(); stage.show(); } - + /** * show a modal dialog * @param parent The dialogs parent */ - public void showModal(Stage parent){ +/* public void showModal(Stage parent){ Stage modalStage = new Stage(); modalStage.initModality(Modality.WINDOW_MODAL); modalStage.initOwner(parent); @@ -53,12 +51,15 @@ public abstract class GuiWindow implements Initializable{ willShow(); modalStage.showAndWait(); } +*/ - public void hide(){ +/* public void hide(){ if(stage != null){ this.stage.hide(); } } +*/ + protected abstract String getTitle(); @@ -72,4 +73,6 @@ public abstract class GuiWindow implements Initializable{ */ public abstract void initialize(URL fxmlFileLocation, ResourceBundle resources); + public abstract void setErrorMessage(String msg); + } diff --git a/src/com/coder/client/gui/editor/EditorWindow.java b/src/com/coder/client/gui/editor/EditorWindow.java index e4dabd7..be07277 100644 --- a/src/com/coder/client/gui/editor/EditorWindow.java +++ b/src/com/coder/client/gui/editor/EditorWindow.java @@ -67,6 +67,13 @@ public class EditorWindow extends GuiWindow { } } + @FXML + protected void chageProject(ActionEvent event){ + for(EditorWindowListener listener : listsners){ + listener.changeProject(); + } + } + private void setupFileTreeView(){ fileTreeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener>() { @Override @@ -118,4 +125,10 @@ public class EditorWindow extends GuiWindow { return "Coder Client"; } + @Override + public void setErrorMessage(String msg) { + // TODO Auto-generated method stub + + } + } diff --git a/src/com/coder/client/gui/editor/EditorWindowListener.java b/src/com/coder/client/gui/editor/EditorWindowListener.java index 3adea4b..29bcda3 100644 --- a/src/com/coder/client/gui/editor/EditorWindowListener.java +++ b/src/com/coder/client/gui/editor/EditorWindowListener.java @@ -5,5 +5,6 @@ public interface EditorWindowListener { public void willShow(); public void compile(); public void run(); + public void changeProject(); } diff --git a/src/com/coder/client/gui/login/LoginDialog.java b/src/com/coder/client/gui/login/LoginDialog.java index 68a859c..818e820 100644 --- a/src/com/coder/client/gui/login/LoginDialog.java +++ b/src/com/coder/client/gui/login/LoginDialog.java @@ -101,6 +101,7 @@ public class LoginDialog extends GuiWindow { return "Login"; } + @Override public void setErrorMessage(String msg) { errorLabel.setText(msg); } diff --git a/src/com/coder/client/gui/newProject/NewProjectDialog.fxml b/src/com/coder/client/gui/newProject/NewProjectDialog.fxml new file mode 100644 index 0000000..1d0d9d8 --- /dev/null +++ b/src/com/coder/client/gui/newProject/NewProjectDialog.fxml @@ -0,0 +1,13 @@ + + + + + + + + + + - + - diff --git a/src/com/coder/client/gui/selectServer/SelectServerDialog.java b/src/com/coder/client/gui/selectServer/SelectServerDialog.java index 1ec8ca4..2da5549 100644 --- a/src/com/coder/client/gui/selectServer/SelectServerDialog.java +++ b/src/com/coder/client/gui/selectServer/SelectServerDialog.java @@ -14,6 +14,7 @@ import javafx.collections.ObservableList; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Button; +import javafx.scene.control.Label; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; import javafx.scene.input.KeyCode; @@ -37,6 +38,7 @@ public class SelectServerDialog extends GuiWindow { @FXML private ListView serverListView; @FXML private Button exitButton; @FXML private Button connectButton; + @FXML private Label errorLabel; public SelectServerDialog() throws IOException { super(SelectServerDialog.class.getResource("SelectServerDialog.fxml")); @@ -57,6 +59,7 @@ public class SelectServerDialog extends GuiWindow { @Override public void initialize(URL fxmlFileLocation, ResourceBundle resources) { + errorLabel.setText(""); serverList = FXCollections.observableArrayList(); serverListView.setItems(serverList); serverListView.setCellFactory(new Callback, ListCell>(){ @@ -146,4 +149,9 @@ public class SelectServerDialog extends GuiWindow { serverList.clear(); } + @Override + public void setErrorMessage(String errorMsg) { + this.errorLabel.setText(errorMsg); + } + }