server
Clone or download
Modified Files
--- 'a/pom.xml'
+++ b/pom.xml
@@ -4,8 +4,8 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
- <groupId>com.StreamPi</groupId>
- <artifactId>Server</artifactId>
+ <groupId>com.stream_pi</groupId>
+ <artifactId>server</artifactId>
<version>1.0.0</version>
<properties>
@@ -33,7 +33,7 @@
<IkonliFA5PackVersion>11.5.0</IkonliFA5PackVersion>
- <MainClassName>com.StreamPi.Server.Main</MainClassName>
+ <MainClassName>com.stream_pi.server.Main</MainClassName>
</properties>
@@ -69,20 +69,20 @@
</dependency>
<dependency>
- <groupId>com.StreamPi</groupId>
- <artifactId>ActionAPI</artifactId>
+ <groupId>com.stream_pi</groupId>
+ <artifactId>action_api</artifactId>
<version>${ActionAPIVersion}</version>
</dependency>
<dependency>
- <groupId>com.StreamPi</groupId>
- <artifactId>Util</artifactId>
+ <groupId>com.stream_pi</groupId>
+ <artifactId>util</artifactId>
<version>${UtilVersion}</version>
</dependency>
<dependency>
- <groupId>com.StreamPi</groupId>
- <artifactId>ThemeAPI</artifactId>
+ <groupId>com.stream_pi</groupId>
+ <artifactId>themeapi</artifactId>
<version>${ThemeAPIVersion}</version>
</dependency>
--- 'a/src/main/java/com/StreamPi/Server/Action/NormalActionPlugins.java'
+++ /dev/null
@@ -1,572 +0,0 @@
-/*
-Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macropad
-Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Written by : Debayan Sutradhar (rnayabed)
-*/
-
-package com.StreamPi.Server.Action;
-
-import com.StreamPi.ActionAPI.Action.Action;
-import com.StreamPi.ActionAPI.Action.ActionType;
-import com.StreamPi.ActionAPI.Action.ServerConnection;
-import com.StreamPi.ActionAPI.Action.PropertySaver;
-import com.StreamPi.ActionAPI.ActionProperty.Property.Property;
-import com.StreamPi.ActionAPI.ActionProperty.Property.Type;
-import com.StreamPi.ActionAPI.ActionProperty.ServerProperties;
-import com.StreamPi.ActionAPI.NormalAction.NormalAction;
-import com.StreamPi.Util.Exception.MinorException;
-import com.StreamPi.Util.Exception.SevereException;
-import com.StreamPi.Util.Exception.StreamPiException;
-import com.StreamPi.Util.Version.Version;
-import com.StreamPi.Util.XMLConfigHelper.XMLConfigHelper;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.transform.Result;
-import javax.xml.transform.Source;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
-import org.w3c.dom.NodeList;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-
-import java.io.File;
-import java.lang.module.*;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ServiceLoader;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.stream.Collectors;
-
-import org.w3c.dom.Element;
-
-public class NormalActionPlugins
-{
- private static NormalActionPlugins instance = null;
- private final Logger logger;
-
- private File configFile;
- private Document document;
-
- private static String pluginsLocation = null;
-
-
- /**
- * Singleton class instance getter. Creates new one, when asked for the first time
- *
- * @return returns instance of NormalActionPlugins (one and only, always)
- */
- public static synchronized NormalActionPlugins getInstance()
- {
- if(instance == null)
- {
- instance = new NormalActionPlugins();
- }
-
- return instance;
- }
-
- /**
- * Sets the folder location where the plugin JARs and their dependencies are stored
- *
- * @param location Folder location
- */
- public static void setPluginsLocation(String location)
- {
- pluginsLocation = location;
- }
-
- /**
- * Private constructor
- */
- private NormalActionPlugins()
- {
- logger = Logger.getLogger(NormalActionPlugins.class.getName());
- normalPluginsHashmap = new HashMap<>();
- }
-
- /**
- * init Method
- */
- public void init() throws SevereException, MinorException
- {
- registerPlugins();
- initPlugins();
- }
-
- /**
- * Used to fetch list of all external Plugins
- *
- * @return List of plugins
- */
- public List<NormalAction> getPlugins()
- {
- return normalPlugins;
- }
-
- /**
- * Returns a plugin by its module name
- *
- * @param name Module Name
- * @return The plugin. If not found, then null is returned
- */
- public NormalAction getPluginByModuleName(String name)
- {
- logger.info("Plugin being requested : "+name);
- Integer index = normalPluginsHashmap.getOrDefault(name, -1);
- if(index != -1)
- {
- return normalPlugins.get(index);
- }
-
- return null;
- }
-
- private List<NormalAction> normalPlugins = null;
- HashMap<String, Integer> normalPluginsHashmap;
-
- /**
- * Used to register plugins from plugin location
- */
- public void registerPlugins() throws SevereException, MinorException
- {
- logger.info("Registering external plugins from "+pluginsLocation+" ...");
-
- try
- {
- configFile = new File(pluginsLocation+"/config.xml");
- DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
- DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
- document = docBuilder.parse(configFile);
- }
- catch (Exception e)
- {
- e.printStackTrace();
- throw new SevereException("Plugins","Error reading plugins config.xml. Cannot continue.");
- }
-
- ArrayList<NormalAction> errorModules = new ArrayList<>();
- ArrayList<String> errorModuleError = new ArrayList<>();
-
- ArrayList<Action> pluginsConfigs = new ArrayList<>();
-
- NodeList actionsNode = document.getElementsByTagName("actions").item(0).getChildNodes();
-
- for(int i =0;i<actionsNode.getLength();i++)
- {
- Node eachActionNode = actionsNode.item(i);
-
- if(eachActionNode.getNodeType() != Node.ELEMENT_NODE)
- continue;
-
- if(!eachActionNode.getNodeName().equals("action"))
- continue;
-
- Element eachActionElement = (Element) eachActionNode;
-
-
-
- String name;
- Version version;
- try
- {
- name = XMLConfigHelper.getStringProperty(eachActionElement, "module-name");
- version = new Version(XMLConfigHelper.getStringProperty(eachActionElement, "version"));
- }
- catch (Exception e)
- {
- logger.log(Level.WARNING, "Skipping configuration because invalid ...");
- e.printStackTrace();
- continue;
- }
-
- ServerProperties serverProperties = new ServerProperties();
-
- NodeList serverPropertiesNodeList = eachActionElement.getElementsByTagName("properties").item(0).getChildNodes();
-
- for(int j = 0;j<serverPropertiesNodeList.getLength();j++)
- {
- Node eachPropertyNode = serverPropertiesNodeList.item(j);
-
-
- if(eachPropertyNode.getNodeType() != Node.ELEMENT_NODE)
- continue;
-
- if(!eachPropertyNode.getNodeName().equals("property"))
- continue;
-
-
- Element eachPropertyElement = (Element) eachPropertyNode;
-
- try
- {
- Property property = new Property(XMLConfigHelper.getStringProperty(eachPropertyElement, "name"), Type.STRING);
- property.setRawValue(XMLConfigHelper.getStringProperty(eachPropertyElement, "value"));
-
- serverProperties.addProperty(property);
- }
- catch (Exception e)
- {
- logger.log(Level.WARNING, "Skipping property because invalid ...");
- e.printStackTrace();
- }
- }
-
- Action action = new Action(ActionType.NORMAL);
-
- action.setModuleName(name);
- action.setVersion(version);
- action.getServerProperties().set(serverProperties);
-
- pluginsConfigs.add(action);
- }
-
- logger.info("Size : "+pluginsConfigs.size());
-
- Path pluginsDir = Paths.get(pluginsLocation); // Directory with plugins JARs
- try
- {
- // Search for plugins in the plugins directory
- ModuleFinder pluginsFinder = ModuleFinder.of(pluginsDir);
-
- // Find all names of all found plugin modules
- List<String> p = pluginsFinder
- .findAll()
- .stream()
- .map(ModuleReference::descriptor)
- .map(ModuleDescriptor::name)
- .collect(Collectors.toList());
-
- // Create configuration that will resolve plugin modules
- // (verify that the graph of modules is correct)
- Configuration pluginsConfiguration = ModuleLayer
- .boot()
- .configuration()
- .resolve(pluginsFinder, ModuleFinder.of(), p);
-
- // Create a module layer for plugins
- ModuleLayer layer = ModuleLayer
- .boot()
- .defineModulesWithOneLoader(pluginsConfiguration, ClassLoader.getSystemClassLoader());
-
- logger.info("Loading plugins from jar ...");
- // Now you can use the new module layer to find service implementations in it
- normalPlugins = ServiceLoader
- .load(layer, NormalAction.class).stream()
- .map(ServiceLoader.Provider::get)
- .collect(Collectors.toList());
-
- logger.info("...Done!");
-
- }
- catch (Exception e)
- {
- e.printStackTrace();
-
- throw new MinorException("Error", "Error loading modules\n"+e.getMessage()+"\nPlease fix the errors. Other plugins wont be loaded.");
- }
-
-
- sortedPlugins = new HashMap<>();
-
- for (NormalAction eachPlugin : normalPlugins)
- {
- try
- {
- eachPlugin.setPropertySaver(propertySaver);
- eachPlugin.setServerConnection(serverConnection);
- eachPlugin.initProperties();
-
- Action foundAction = null;
- for (Action action : pluginsConfigs) {
- if (action.getModuleName().equals(eachPlugin.getModuleName())
- && action.getVersion().isEqual(eachPlugin.getVersion())) {
-
- foundAction = action;
-
- List<Property> eachPluginStoredProperties = action.getServerProperties().get();
- List<Property> eachPluginCodeProperties = eachPlugin.getServerProperties().get();
-
-
- for (int i =0;i< eachPluginCodeProperties.size(); i++) {
-
- Property eachPluginCodeProperty = eachPluginCodeProperties.get(i);
-
- Property foundProp = null;
- for (Property eachPluginStoredProperty : eachPluginStoredProperties) {
- if (eachPluginCodeProperty.getName().equals(eachPluginStoredProperty.getName())) {
- eachPluginCodeProperty.setRawValue(eachPluginStoredProperty.getRawValue());
- foundProp = eachPluginStoredProperty;
- }
- }
-
- eachPluginCodeProperties.set(i, eachPluginCodeProperty);
-
- if (foundProp != null) {
- eachPluginStoredProperties.remove(foundProp);
- }
- }
-
-
- eachPlugin.getServerProperties().set(eachPluginCodeProperties);
-
- break;
- }
- }
-
- if (foundAction != null)
- pluginsConfigs.remove(foundAction);
- else
- {
- List<Property> eachPluginStoredProperties = eachPlugin.getServerProperties().get();
- for(Property property :eachPluginStoredProperties)
- {
- if(property.getType() == Type.STRING || property.getType() == Type.INTEGER || property.getType() == Type.DOUBLE)
- property.setRawValue(property.getDefaultRawValue());
- }
- }
-
-
-
- if (!sortedPlugins.containsKey(eachPlugin.getCategory())) {
- ArrayList<NormalAction> actions = new ArrayList<>();
-
- sortedPlugins.put(eachPlugin.getCategory(), actions);
- }
-
- sortedPlugins.get(eachPlugin.getCategory()).add(eachPlugin);
-
- }
- catch (Exception e)
- {
- e.printStackTrace();
- errorModules.add(eachPlugin);
- errorModuleError.add(e.getMessage());
- }
- }
-
- try {
- saveServerSettings();
- } catch (MinorException e) {
- e.printStackTrace();
- }
-
- logger.log(Level.INFO, "All plugins registered!");
-
- if(errorModules.size() > 0)
- {
- StringBuilder errors = new StringBuilder("The following action modules could not be loaded:");
- for(int i = 0; i<errorModules.size(); i++)
- {
- normalPlugins.remove(errorModules.get(i));
- errors.append("\n * ").append(errorModules.get(i).getModuleName()).append("\n(")
- .append(errorModuleError.get(i)).append(")");
- }
-
- throw new MinorException("Plugins", errors.toString());
- }
-
-
- for(int i = 0;i<normalPlugins.size();i++)
- {
- normalPluginsHashmap.put(normalPlugins.get(i).getModuleName(), i);
- }
- }
-
- /**
- * Used to init plugins
- */
- public void initPlugins() throws MinorException
- {
- StringBuilder errors = new StringBuilder("There were errors registering the following plugins. As a result, they have been omitted : ");
- boolean isError = false;
-
- for(NormalAction eachPlugin : normalPlugins)
- {
- try
- {
- eachPlugin.initAction();
- }
- catch (Exception e)
- {
- e.printStackTrace();
- isError = true;
- errors.append("\n* ")
- .append(eachPlugin.getName())
- .append(" - ")
- .append(eachPlugin.getModuleName())
- .append("\n");
-
- if(e instanceof StreamPiException)
- errors.append(((MinorException) e).getShortMessage());
-
- errors.append("\n");
- }
- }
-
- if(isError)
- {
- throw new MinorException("Plugin init error", errors.toString());
- }
- }
-
- HashMap<String, ArrayList<NormalAction>> sortedPlugins;
-
- /**
- * Gets list of sorted plugins
- *
- * @return Hashmap with category key, and list of plugins of each category
- */
- public HashMap<String, ArrayList<NormalAction>> getSortedPlugins()
- {
- return sortedPlugins;
- }
-
- /**
- * @return Gets actions element from the config.xml in plugins folder
- */
- private Element getActionsElement()
- {
- return (Element) document.getElementsByTagName("actions").item(0);
- }
-
- /**
- * Saves ServerProperties of every plugin in config.xml in plugins folder
- *
- * @throws MinorException Thrown when failed to save settings
- */
- public void saveServerSettings() throws MinorException
- {
- XMLConfigHelper.removeChilds(getActionsElement());
-
- for(NormalAction normalAction : normalPlugins)
- {
- Element actionElement = document.createElement("action");
- getActionsElement().appendChild(actionElement);
-
- Element moduleNameElement = document.createElement("module-name");
- moduleNameElement.setTextContent(normalAction.getModuleName());
- actionElement.appendChild(moduleNameElement);
-
-
- Element versionElement = document.createElement("version");
- versionElement.setTextContent(normalAction.getVersion().getText());
- actionElement.appendChild(versionElement);
-
- Element propertiesElement = document.createElement("properties");
- actionElement.appendChild(propertiesElement);
-
- for(String key : normalAction.getServerProperties().getNames())
- {
- for(Property eachProperty : normalAction.getServerProperties().getMultipleProperties(key))
- {
- Element propertyElement = document.createElement("property");
- propertiesElement.appendChild(propertyElement);
-
- Element nameElement = document.createElement("name");
- nameElement.setTextContent(eachProperty.getName());
- propertyElement.appendChild(nameElement);
-
- Element valueElement = document.createElement("value");
- valueElement.setTextContent(eachProperty.getRawValue());
- propertyElement.appendChild(valueElement);
- }
- }
- }
-
- save();
- }
-
- private PropertySaver propertySaver = null;
-
- /**
- * Set PropertySaver class
- * @param propertySaver instance of PropertySaver
- */
- public void setPropertySaver(PropertySaver propertySaver)
- {
- this.propertySaver = propertySaver;
- }
-
- private ServerConnection serverConnection = null;
-
- /**
- * Set setServerConnection class
- * @param serverConnection instance of ServerConnection
- */
- public void setServerConnection(ServerConnection serverConnection)
- {
- this.serverConnection = serverConnection;
- }
-
- /**
- * Get plugin from index from list
- *
- * @param index of plugin
- * @return found plugin
- */
- public NormalAction getActionFromIndex(int index)
- {
- return normalPlugins.get(index);
- }
-
- /**
- * Calls onShutDown method in every plugin
- */
- public void shutDownActions()
- {
- if(normalPlugins != null)
- {
- for(NormalAction eachPlugin : normalPlugins)
- {
- try
- {
- eachPlugin.onShutDown();
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
-
- normalPlugins.clear();
- }
- }
-
- /**
- * Saves all Server Properties of each Plugin in config.xml in Plugins folder
- * @throws MinorException thrown when failed to save
- */
- public void save() throws MinorException
- {
- try
- {
- Transformer transformer = TransformerFactory.newInstance().newTransformer();
- Result output = new StreamResult(configFile);
- Source input = new DOMSource(document);
-
- transformer.transform(input, output);
- }
- catch (Exception e)
- {
- throw new MinorException("Config", "unable to save server plugins settings");
- }
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/Client/Client.java'
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
-Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macropad
-Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Written by : Debayan Sutradhar (rnayabed)
-*/
-
-package com.StreamPi.Server.Client;
-
-import com.StreamPi.Util.Platform.Platform;
-import com.StreamPi.Util.Platform.ReleaseStatus;
-import com.StreamPi.Util.Version.Version;
-
-import java.net.SocketAddress;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-public class Client {
- private String nickName;
- private final SocketAddress remoteSocketAddress;
- private final Platform platform;
- private final Version version;
- private final Version commStandardVersion;
- private final Version themeAPIVersion;
- private final ReleaseStatus releaseStatus;
-
- private double startupDisplayHeight, startupDisplayWidth;
-
- private final HashMap<String,ClientProfile> profiles;
-
- private final HashMap<String,ClientTheme> themes;
-
- private String defaultProfileID;
- private String defaultThemeFullName;
-
- public Client(Version version, ReleaseStatus releaseStatus, Version commStandardVersion, Version themeAPIVersion, String nickName, Platform platform, SocketAddress remoteSocketAddress)
- {
- this.version = version;
- this.releaseStatus = releaseStatus;
- this.commStandardVersion = commStandardVersion;
- this.themeAPIVersion = themeAPIVersion;
- this.nickName = nickName;
- this.remoteSocketAddress = remoteSocketAddress;
- this.platform = platform;
- this.profiles = new HashMap<>();
- this.themes = new HashMap<>();
- }
-
- public ReleaseStatus getReleaseStatus() {
- return releaseStatus;
- }
-
- public void setDefaultThemeFullName(String defaultThemeFullName) {
- this.defaultThemeFullName = defaultThemeFullName;
- }
-
- public String getDefaultThemeFullName() {
- return defaultThemeFullName;
- }
-
- public void setDefaultProfileID(String ID)
- {
- defaultProfileID = ID;
- }
-
- public void addTheme(ClientTheme clientTheme) throws CloneNotSupportedException
- {
- themes.put(clientTheme.getThemeFullName(), (ClientTheme) clientTheme.clone());
- }
-
- public ArrayList<ClientTheme> getThemes()
- {
- ArrayList<ClientTheme> clientThemes = new ArrayList<>();
- for(String clientTheme : themes.keySet())
- {
- clientThemes.add(themes.get(clientTheme));
- }
- return clientThemes;
- }
-
- public ClientTheme getThemeByFullName(String fullName)
- {
- return themes.getOrDefault(fullName, null);
- }
-
- public String getDefaultProfileID()
- {
- return defaultProfileID;
- }
-
- //Client Profiles
-
- public void setNickName(String nickName)
- {
- this.nickName = nickName;
- }
-
- public List<ClientProfile> getAllClientProfiles()
- {
- ArrayList<ClientProfile> clientProfiles = new ArrayList<>();
- for(String profile : profiles.keySet())
- clientProfiles.add(profiles.get(profile));
- return clientProfiles;
- }
-
- public void removeProfileFromID(String ID)
- {
- profiles.remove(ID);
- }
-
- public void addProfile(ClientProfile clientProfile) throws CloneNotSupportedException {
- profiles.put(clientProfile.getID(), (ClientProfile) clientProfile.clone());
- }
-
- public synchronized ClientProfile getProfileByID(String ID) {
- return profiles.getOrDefault(ID, null);
- }
-
- public SocketAddress getRemoteSocketAddress()
- {
- return remoteSocketAddress;
- }
-
- public Platform getPlatform()
- {
- return platform;
- }
-
- public String getNickName()
- {
- return nickName;
- }
-
- public Version getVersion()
- {
- return version;
- }
-
- public Version getCommStandardVersion()
- {
- return commStandardVersion;
- }
-
- public Version getThemeAPIVersion()
- {
- return themeAPIVersion;
- }
-
- public double getStartupDisplayHeight()
- {
- return startupDisplayHeight;
- }
-
- public double getStartupDisplayWidth()
- {
- return startupDisplayWidth;
- }
-
- public void setStartupDisplayHeight(double height)
- {
- startupDisplayHeight = height;
- }
-
- public void setStartupDisplayWidth(double width)
- {
- startupDisplayWidth = width;
- }
-
- private int getMaxRows(int eachActionSize)
- {
- return (int) (startupDisplayHeight / eachActionSize);
- }
-
- public int getMaxCols(int eachActionSize)
- {
- return (int) (startupDisplayWidth / eachActionSize);
- }
-
-}
--- 'a/src/main/java/com/StreamPi/Server/Client/ClientProfile.java'
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
-Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macropad
-Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Written by : Debayan Sutradhar (rnayabed)
-*/
-
-package com.StreamPi.Server.Client;
-
-import com.StreamPi.ActionAPI.Action.Action;
-import java.util.HashMap;
-import java.util.Set;
-import java.util.UUID;
-
-public class ClientProfile implements Cloneable {
-
- private String name, ID;
-
- private int rows, cols, actionSize, actionGap;
-
- private final HashMap<String, Action> actions;
-
- public ClientProfile(String name, String ID, int rows, int cols, int actionSize, int actionGap)
- {
- this.actions = new HashMap<>();
- this.ID = ID;
- this.name = name;
- this.rows = rows;
- this.cols = cols;
- this.actionGap = actionGap;
- this.actionSize = actionSize;
- }
-
- public ClientProfile(String name, int rows, int cols, int actionSize, int actionGap)
- {
- this(name, UUID.randomUUID().toString(), rows, cols, actionSize, actionGap);
- }
-
- public Action getActionByID(String ID)
- {
- return actions.get(ID);
- }
-
- public void removeActionByID(String ID)
- {
- actions.remove(ID);
- }
-
-
- public Set<String> getActionsKeySet() {
- return actions.keySet();
- }
-
- public synchronized void addAction(Action action) throws CloneNotSupportedException {
- actions.put(action.getID(), action.clone());
- }
-
- public String getID()
- {
- return ID;
- }
-
- public String getName()
- {
- return name;
- }
-
- public int getRows()
- {
- return rows;
- }
-
- public int getCols()
- {
- return cols;
- }
-
- public int getActionSize()
- {
- return actionSize;
- }
-
- public int getActionGap()
- {
- return actionGap;
- }
-
- public void setRows(int rows)
- {
- this.rows = rows;
- }
-
- public void setCols(int cols)
- {
- this.cols = cols;
- }
-
- public void setID(String ID)
- {
- this.ID = ID;
- }
-
- public void setActionSize(int actionSize)
- {
- this.actionSize = actionSize;
- }
-
- public void setActionGap(int actionGap)
- {
- this.actionGap = actionGap;
- }
-
- public void setName(String name)
- {
- this.name = name;
- }
-
-
- public Object clone() throws CloneNotSupportedException
- {
- return super.clone();
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/Client/ClientTheme.java'
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.StreamPi.Server.Client;
-
-public class ClientTheme implements Cloneable
-{
- public String themeFullName;
- public String shortName;
- public String author;
- public String version;
-
- public ClientTheme(String themeFullName, String shortName,
- String author, String version)
- {
- this.themeFullName = themeFullName;
- this.shortName = shortName;
- this.author = author;
- this.version = version;
- }
-
- public String getThemeFullName()
- {
- return themeFullName;
- }
-
- public String getShortName()
- {
- return shortName;
- }
-
- public String getAuthor()
- {
- return author;
- }
-
- public String getVersion() {
- return version;
- }
-
- public Object clone() throws CloneNotSupportedException
- {
- return super.clone();
- }
-}
\ No newline at end of file
--- 'a/src/main/java/com/StreamPi/Server/Connection/ClientConnection.java'
+++ /dev/null
@@ -1,901 +0,0 @@
-package com.StreamPi.Server.Connection;
-
-import com.StreamPi.ActionAPI.Action.Action;
-import com.StreamPi.ActionAPI.Action.ActionType;
-import com.StreamPi.ActionAPI.Action.DisplayTextAlignment;
-import com.StreamPi.ActionAPI.Action.Location;
-import com.StreamPi.ActionAPI.ActionProperty.ClientProperties;
-import com.StreamPi.ActionAPI.ActionProperty.Property.Property;
-import com.StreamPi.ActionAPI.ActionProperty.Property.Type;
-import com.StreamPi.ActionAPI.NormalAction.NormalAction;
-import com.StreamPi.ActionAPI.OtherActions.CombineAction;
-import com.StreamPi.ActionAPI.OtherActions.FolderAction;
-import com.StreamPi.Server.Action.NormalActionPlugins;
-import com.StreamPi.Server.Client.Client;
-import com.StreamPi.Server.Client.ClientProfile;
-import com.StreamPi.Server.Client.ClientTheme;
-import com.StreamPi.Server.Info.ServerInfo;
-import com.StreamPi.Server.Window.ExceptionAndAlertHandler;
-import com.StreamPi.Util.Alert.StreamPiAlert;
-import com.StreamPi.Util.Alert.StreamPiAlertType;
-import com.StreamPi.Util.Exception.MinorException;
-import com.StreamPi.Util.Exception.SevereException;
-import com.StreamPi.Util.Exception.StreamPiException;
-import com.StreamPi.Util.Platform.Platform;
-import com.StreamPi.Util.Platform.ReleaseStatus;
-import com.StreamPi.Util.Version.Version;
-import javafx.concurrent.Task;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.SocketException;
-import java.net.SocketTimeoutException;
-import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.stream.Stream;
-
-public class ClientConnection extends Thread{
- private Socket socket;
- private ServerListener serverListener;
- private AtomicBoolean stop = new AtomicBoolean(false);
-
- private DataInputStream dis;
- private DataOutputStream dos;
-
- private Logger logger;
-
- private Client client = null;
-
- private ExceptionAndAlertHandler exceptionAndAlertHandler;
-
- public ClientConnection(Socket socket, ServerListener serverListener, ExceptionAndAlertHandler exceptionAndAlertHandler)
- {
- this.exceptionAndAlertHandler = exceptionAndAlertHandler;
- //actionIconsToBeSent = new ArrayList__();
- this.socket = socket;
-
- this.serverListener = serverListener;
-
- logger = Logger.getLogger(ClientConnection.class.getName());
-
- try
- {
- dis = new DataInputStream(socket.getInputStream());
- dos = new DataOutputStream(socket.getOutputStream());
- } catch (IOException e) {
- e.printStackTrace();
-
- exceptionAndAlertHandler.handleMinorException(new MinorException("Unable to start socket streams"));
- }
-
- start();
- }
-
- public synchronized void exit()
- {
- if(stop.get())
- return;
-
- logger.info("Stopping ...");
-
- try
- {
- if(socket !=null)
- {
- logger.info("Stopping connection "+socket.getRemoteSocketAddress());
- disconnect();
- }
- }
- catch (SevereException e)
- {
- e.printStackTrace();
- exceptionAndAlertHandler.handleSevereException(e);
- }
- }
-
- public synchronized void exitAndRemove()
- {
- exit();
- removeConnection();
- serverListener.clearTemp();
- }
-
- public void removeConnection()
- {
- ClientConnections.getInstance().removeConnection(this);
- }
-
-
- public void writeToStream(String text) throws SevereException
- {
- /*try
- {
- logger.debug(text);
- dos.writeUTF(text);
- dos.flush();
- }
- catch (IOException e)
- {
- e.printStackTrace();
- throw new SevereException("Unable to write to IO Stream!");
- }*/
-
- try
- {
- byte[] txtBytes = text.getBytes();
-
- Thread.sleep(50);
- dos.writeUTF("string:: ::");
- dos.flush();
- dos.writeInt(txtBytes.length);
- dos.flush();
- write(txtBytes);
- dos.flush();
- }
- catch (IOException | InterruptedException e)
- {
- e.printStackTrace();
- throw new SevereException("Unable to write to IO Stream!");
- }
-
- }
-
- public void sendIcon(String profileID, String actionID, byte[] icon) throws SevereException
- {
- try
- {
- logger.info("Sending action Icon...");
- //Thread.sleep(50);
- System.out.println("1");
- dos.writeUTF("action_icon::"+profileID+"!!"+actionID+"!!::"+icon.length);
-
- System.out.println("2");
- dos.flush();
-
- System.out.println("3");
- dos.writeInt(icon.length);
-
- System.out.println("4");
- dos.flush();
-
- System.out.println("5");
- write(icon);
-
- System.out.println("6");
- dos.flush();
-
- System.out.println("7");
- }
- catch (IOException e)
- {
- e.printStackTrace();
- throw new SevereException("Unable to write to IO Stream!");
- }
- }
-
- public void write(byte[] array) throws SevereException
- {
- try
- {
- dos.write(array);
- }
- catch (IOException e)
- {
- e.printStackTrace();
- throw new SevereException("Unable to write to IO Stream!");
- }
- }
-
-
- public void initAfterConnectionQueryReceive(String[] arr) throws StreamPiException
- {
- logger.info("Setting up Client object ...");
-
- Version clientVersion;
- Version commsStandard;
- Version themesStandard;
-
- ReleaseStatus releaseStatus;
-
- try
- {
- clientVersion = new Version(arr[1]);
- releaseStatus = ReleaseStatus.valueOf(arr[2]);
- commsStandard = new Version(arr[3]);
- themesStandard = new Version(arr[4]);
- }
- catch (MinorException e)
- {
- exitAndRemove();
- throw new MinorException(e.getShortMessage()+" (Client '"+socket.getRemoteSocketAddress()+"' )");
- }
-
- if(!commsStandard.isEqual(ServerInfo.getInstance().getCommStandardVersion()))
- {
- String errTxt = "Server and Client Communication standards do not match. Make sure you are on the latest version of server and client.\n" +
- "Server Comms. Standard : "+ServerInfo.getInstance().getCommStandardVersion().getText()+
- "\nClient Comms. Standard : "+commsStandard.getText();
-
- disconnect(errTxt);
- throw new MinorException(errTxt);
- }
-
- client = new Client(clientVersion, releaseStatus, commsStandard, themesStandard, arr[5], Platform.valueOf(arr[8]), socket.getRemoteSocketAddress());
-
- client.setStartupDisplayWidth(Double.parseDouble(arr[6]));
- client.setStartupDisplayHeight(Double.parseDouble(arr[7]));
- client.setDefaultProfileID(arr[9]);
- client.setDefaultThemeFullName(arr[10]);
-
- //call get profiles command.
- serverListener.clearTemp();
- }
-
- public synchronized Client getClient()
- {
- return client;
- }
-
- @Override
- public void run() {
-
- try {
- initAfterConnectionQuerySend();
- } catch (SevereException e) {
- e.printStackTrace();
-
- exceptionAndAlertHandler.handleSevereException(e);
-
- exitAndRemove();
- return;
- }
-
- try
- {
- while(!stop.get())
- {
- String msg = "";
-
- try
- {
- String raw = dis.readUTF();
-
- int length = dis.readInt();
-
- System.out.println("SIZE TO READ : "+length);
-
- String[] precursor = raw.split("::");
-
- String inputType = precursor[0];
- String secondArg = precursor[1];
-
-
- ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
-
- /*int count;
- int chunkSize = 512;
- while (length>0)
- {
- if(chunkSize > length)
- chunkSize = length;
- else
- chunkSize = 512;
-
- byte[] buffer = new byte[chunkSize];
- count = dis.read(buffer);
-
- System.out.println(count);
-
- byteArrayOutputStream.write(buffer);
-
- length-=count;
- }*/
-
- /*byte[] buffer = new byte[8192];
- int read;
- while((read = dis.read(buffer)) != -1){
- System.out.println("READ : "+read);
- byteArrayOutputStream.write(buffer, 0, read);
- }
-
- System.out.println("READ : "+byteArrayOutputStream.size());
-
- byteArrayOutputStream.close();
-
- byte[] bArr = byteArrayOutputStream.toByteArray();*/
-
- byte[] bArr = new byte[length];
-
- dis.readFully(bArr);
-
- if(inputType.equals("string"))
- {
- msg = new String(bArr);
- }
- else if(inputType.equals("action_icon"))
- {
- String[] secondArgSep = secondArg.split("!!");
-
- String profileID = secondArgSep[0];
- String actionID = secondArgSep[1];
-
- getClient().getProfileByID(profileID).getActionByID(actionID).setIcon(bArr);
-
- //serverListener.clearTemp();
- continue;
- }
- }
- catch (IOException e)
- {
- logger.log(Level.SEVERE, e.getMessage());
- e.printStackTrace();
-
- serverListener.clearTemp();
-
- if(!stop.get())
- {
- removeConnection();
- throw new MinorException("Accidentally disconnected from "+getClient().getNickName()+".");
- }
-
- exitAndRemove();
-
- return;
- }
-
- logger.info("Received text : '"+msg+"'");
-
- String[] sep = msg.split("::");
-
- String command = sep[0];
-
- switch (command)
- {
- case "disconnect" : clientDisconnected(msg);
- break;
-
- case "client_details" : initAfterConnectionQueryReceive(sep);
- getProfilesFromClient();
- getThemesFromClient();
- break;
-
- case "profiles" : registerProfilesFromClient(sep);
- break;
-
- case "profile_details" : registerProfileDetailsFromClient(sep);
- break;
-
- case "action_details" : registerActionToProfile(sep);
- break;
-
- case "themes": registerThemes(sep);
- break;
-
- case "action_clicked": actionClicked(sep[1], sep[2]);
- break;
-
- default: logger.warning("Command '"+command+"' does not match records. Make sure client and server versions are equal.");
-
-
- }
- }
- }
- catch (StreamPiException e)
- {
- e.printStackTrace();
-
-
- if(e instanceof MinorException)
- exceptionAndAlertHandler.handleMinorException((MinorException) e);
- else if (e instanceof SevereException)
- exceptionAndAlertHandler.handleSevereException((SevereException) e);
-
- }
- }
-
-
-
-
-
-
- // commands
-
- public void initAfterConnectionQuerySend() throws SevereException
- {
- logger.info("Asking client details ...");
- writeToStream("get_client_details::");
- }
-
- public void disconnect() throws SevereException {
- disconnect("");
- }
-
- public void disconnect(String message) throws SevereException {
- if(stop.get())
- return;
-
- stop.set(true);
-
- logger.info("Sending client disconnect message ...");
- writeToStream("disconnect::"+message+"::");
-
-
- try
- {
- if(!socket.isClosed())
- socket.close();
- }
- catch (IOException e)
- {
- e.printStackTrace();
- throw new SevereException("Unable to close socket");
- }
- }
-
- public void clientDisconnected(String message)
- {
- stop.set(true);
- String txt = "Disconnected!";
-
- if(!message.equals("disconnect::::"))
- txt = "Message : "+message.split("::")[1];
-
- new StreamPiAlert("Disconnected from "+getClient().getNickName()+".", txt, StreamPiAlertType.WARNING).show();;
- exitAndRemove();
- }
-
- public void getProfilesFromClient() throws StreamPiException
- {
- logger.info("Asking client to send profiles ...");
- writeToStream("get_profiles::");
- }
-
- public void getThemesFromClient() throws StreamPiException
- {
- logger.info("Asking clients to send themes ...");
- writeToStream("get_themes::");
- }
-
- public void registerThemes(String[] sep)
- {
- for(int i =1; i<sep.length;i++)
- {
- String[] internal = sep[i].split("__");
-
- ClientTheme clientTheme = new ClientTheme(
- internal[0],
- internal[1],
- internal[2],
- internal[3]
- );
-
- try
- {
- getClient().addTheme(clientTheme);
- }
- catch (CloneNotSupportedException e)
- {
- logger.log(Level.SEVERE, e.getMessage());
- e.printStackTrace();
- }
- }
- }
-
- public void registerProfilesFromClient(String[] sep) throws StreamPiException
- {
- logger.info("Registering profiles ...");
-
- int noOfProfiles = Integer.parseInt(sep[1]);
-
- for(int i = 2; i<(noOfProfiles + 2); i++)
- {
- String profileID = sep[i];
- getProfileDetailsFromClient(profileID);
- }
- }
-
- public void getProfileDetailsFromClient(String ID) throws StreamPiException
- {
- logger.info("Asking client to send details of profile : "+ID);
- writeToStream("get_profile_details::"+ID+"::");
- }
-
-
- public void registerProfileDetailsFromClient(String[] sep)
- {
- String ID = sep[1];
- logger.info("Registering details for profile : "+ID);
-
- String name = sep[2];
- int rows = Integer.parseInt(sep[3]);
- int cols = Integer.parseInt(sep[4]);
- int actionSize = Integer.parseInt(sep[5]);
- int actionGap = Integer.parseInt(sep[6]);
-
-
- ClientProfile clientProfile = new ClientProfile(name, ID, rows, cols, actionSize, actionGap);
-
- logger.info("Added client profile "+clientProfile.getName());
- try
- {
- getClient().addProfile(clientProfile);
- }
- catch (CloneNotSupportedException e)
- {
- logger.severe(e.getMessage());
- e.printStackTrace();
- }
- serverListener.clearTemp();
- }
-
- /*public void getActionIcon(String profileID, String actionID) throws StreamPiException
- {
- System.out.println("getting action icon from "+profileID+", "+actionID);
- writeToStream("get_action_icon::"+profileID+"::"+actionID);
- }*/
-
- public synchronized void registerActionToProfile(String[] sep) throws StreamPiException
- {
- String profileID = sep[1];
-
- String ID = sep[2];
- ActionType actionType = ActionType.valueOf(sep[3]);
-
- //4 - Version
- //5 - ModuleName
-
- //display
- String bgColorHex = sep[6];
-
- //icon
- boolean isHasIcon = sep[7].equals("true");
- boolean isShowIcon = sep[8].equals("true");
-
- //text
- boolean isShowDisplayText = sep[9].equals("true");
- String displayFontColor = sep[10];
- String displayText = sep[11];
- DisplayTextAlignment displayTextAlignment = DisplayTextAlignment.valueOf(sep[12]);
-
- //location
- String row = sep[13];
- String col = sep[14];
-
- Location location = new Location(Integer.parseInt(row), Integer.parseInt(col));
-
-
-
- Action action = new Action(ID, actionType);
-
- action.setBgColourHex(bgColorHex);
- action.setShowIcon(isShowIcon);
- action.setHasIcon(isHasIcon);
-
- action.setShowDisplayText(isShowDisplayText);
- action.setDisplayTextFontColourHex(displayFontColor);
- action.setDisplayText(displayText);
- action.setDisplayTextAlignment(displayTextAlignment);
-
-
- action.setLocation(location);
-
-
- //client properties
-
- int clientPropertiesSize = Integer.parseInt(sep[15]);
-
- String root = sep[17];
- action.setParent(root);
-
- String[] clientPropertiesRaw = sep[16].split("!!");
-
- ClientProperties clientProperties = new ClientProperties();
-
- if(actionType == ActionType.FOLDER)
- clientProperties.setDuplicatePropertyAllowed(true);
-
- for(int i = 0;i<clientPropertiesSize; i++)
- {
- String[] clientPraw = clientPropertiesRaw[i].split("__");
-
- Property property = new Property(clientPraw[0], Type.STRING);
-
- if(clientPraw.length > 1)
- property.setRawValue(clientPraw[1]);
-
- clientProperties.addProperty(property);
- }
-
- action.setClientProperties(clientProperties);
- action.setModuleName(sep[5]);
-
- //set up action
-
- //Action toBeAdded = null;
-
- if(actionType == ActionType.NORMAL)
- {
- NormalAction actionCopy = NormalActionPlugins.getInstance().getPluginByModuleName(sep[5]);
-
- if(actionCopy == null)
- {
- action.setInvalid(true);
- }
- else
- {
- action.setVersion(new Version(sep[4]));
-
- //action.setHelpLink(actionCopy.getHelpLink());
-
- if(actionCopy.getVersion().getMajor() != action.getVersion().getMajor())
- {
- action.setInvalid(true);
- }
- else
- {
- action.setName(actionCopy.getName());
-
- ClientProperties finalClientProperties = new ClientProperties();
-
-
- for(Property property : actionCopy.getClientProperties().get())
- {
- for(int i = 0;i<action.getClientProperties().getSize();i++)
- {
- Property property1 = action.getClientProperties().get().get(i);
- if (property.getName().equals(property1.getName()))
- {
- property.setRawValue(property1.getRawValue());
-
-
- finalClientProperties.addProperty(property);
- }
- }
- }
-
- action.setClientProperties(finalClientProperties);
-
- }
- }
- }
-
-
- try
- {
- for(Property prop : action.getClientProperties().get())
- {
- logger.info("G@@@@@ : "+prop.getRawValue());
- }
-
-
- getClient().getProfileByID(profileID).addAction(action);
-
-
-
- for(String action1x : getClient().getProfileByID(profileID).getActionsKeySet())
- {
- Action action1 = getClient().getProfileByID(profileID).getActionByID(action1x);
- logger.info("231cc : "+action1.getID());
- for(Property prop : action1.getClientProperties().get())
- {
- logger.info("G@VVVV@@@ : "+prop.getRawValue());
- }
- }
-
- }
- catch (CloneNotSupportedException e)
- {
- e.printStackTrace();
- exceptionAndAlertHandler.handleMinorException(new MinorException("Action", "Unable to clone"));
- }
-
- }
-
- public void saveActionDetails(String profileID, Action action) throws SevereException
- {
- StringBuilder finalQuery = new StringBuilder("save_action_details::");
-
-
- //failsafes
-
- if(action.getDisplayText().endsWith(":"))
- action.setDisplayText(action.getDisplayText()+" ");
-
-
- finalQuery.append(profileID)
- .append("::")
- .append(action.getID())
- .append("::")
- .append(action.getActionType())
- .append("::");
-
- if(action.getActionType() == ActionType.NORMAL)
- {
- finalQuery.append(action.getVersion().getText());
- System.out.println("VERSION :sdd "+action.getVersion().getText());
- }
-
- finalQuery.append("::");
-
- if(action.getActionType() == ActionType.NORMAL)
- finalQuery.append(action.getModuleName());
-
- finalQuery.append("::");
-
- //display
-
- finalQuery.append(action.getBgColourHex())
- .append("::");
-
- //icon
- finalQuery.append(action.isHasIcon())
- .append("::")
- .append(action.isShowIcon())
- .append("::");
-
- //text
- finalQuery.append(action.isShowDisplayText())
- .append("::")
- .append(action.getDisplayTextFontColourHex())
- .append("::")
- .append(action.getDisplayText())
- .append("::")
- .append(action.getDisplayTextAlignment())
- .append("::");
-
- //location
-
- if(action.getLocation() == null)
- finalQuery.append("-1::-1::");
- else
- finalQuery.append(action.getLocation().getRow())
- .append("::")
- .append(action.getLocation().getCol())
- .append("::");
-
- //client properties
-
- ClientProperties clientProperties = action.getClientProperties();
-
- finalQuery.append(clientProperties.getSize())
- .append("::");
-
- for(Property property : clientProperties.get())
- {
- finalQuery.append(property.getName())
- .append("__")
- .append(property.getRawValue())
- .append("__");
-
- finalQuery.append("!!");
- }
-
- finalQuery.append("::")
- .append(action.getParent())
- .append("::");
-
- writeToStream(finalQuery.toString());
-
- }
-
- public void deleteAction(String profileID, String actionID) throws SevereException
- {
- writeToStream("delete_action::"+profileID+"::"+actionID);
- }
-
- public void saveClientDetails(String clientNickname, String screenWidth, String screenHeight, String defaultProfileID,
- String defaultThemeFullName) throws SevereException
- {
- writeToStream("save_client_details::"+
- clientNickname+"::"+
- screenWidth+"::"+
- screenHeight+"::"+
- defaultProfileID+"::"+
- defaultThemeFullName+"::");
-
- client.setNickName(clientNickname);
- client.setStartupDisplayWidth(Double.parseDouble(screenWidth));
- client.setStartupDisplayHeight(Double.parseDouble(screenHeight));
- client.setDefaultProfileID(defaultProfileID);
- client.setDefaultThemeFullName(defaultThemeFullName);
- }
-
- public void saveProfileDetails(ClientProfile clientProfile) throws SevereException, CloneNotSupportedException {
- if(client.getProfileByID(clientProfile.getID()) !=null)
- {
- client.getProfileByID(clientProfile.getID()).setName(clientProfile.getName());
- client.getProfileByID(clientProfile.getID()).setRows(clientProfile.getRows());
- client.getProfileByID(clientProfile.getID()).setCols(clientProfile.getCols());
- client.getProfileByID(clientProfile.getID()).setActionSize(clientProfile.getActionSize());
- client.getProfileByID(clientProfile.getID()).setActionGap(clientProfile.getActionGap());
- }
- else
- client.addProfile(clientProfile);
-
- writeToStream("save_client_profile::"+
- clientProfile.getID()+"::"+
- clientProfile.getName()+"::"+
- clientProfile.getRows()+"::"+
- clientProfile.getCols()+"::"+
- clientProfile.getActionSize()+"::"+
- clientProfile.getActionGap()+"::");
- }
-
- public void deleteProfile(String ID) throws SevereException
- {
- writeToStream("delete_profile::"+ID+"::");
- }
-
- public void actionClicked(String profileID, String actionID) {
-
- try
- {
- Action action = client.getProfileByID(profileID).getActionByID(actionID);
-
- if(action.getActionType() == ActionType.NORMAL)
- {
- NormalAction original = NormalActionPlugins.getInstance().getPluginByModuleName(
- action.getModuleName()
- );
-
- if(original == null)
- {
- throw new MinorException(
- "The Action isn't installed on the server."
- );
- }
-
- NormalAction normalAction = original.clone();
-
-
-
- normalAction.setLocation(action.getLocation());
- normalAction.setDisplayText(action.getDisplayText());
- normalAction.setID(actionID);
-
- normalAction.setClientProperties(action.getClientProperties());
-
- new Thread(new Task<Void>() {
- @Override
- protected Void call()
- {
- try
- {
- boolean result = serverListener.onNormalActionClicked(normalAction);
- if(!result)
- {
- sendActionFailed(profileID, actionID);
- }
- }
- catch (SevereException e)
- {
- exceptionAndAlertHandler.handleSevereException(e);
- }
- return null;
- }
- }).start();
- }
- } catch (Exception e) {
- e.printStackTrace();
- exceptionAndAlertHandler.handleMinorException(new MinorException(e.getMessage()));
- }
- }
-
- public void sendActionFailed(String profileID, String actionID) throws SevereException {
- logger.info("Sending failed status ...");
- writeToStream("action_failed::"+
- profileID+"::"+
- actionID+"::");
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/Connection/ClientConnections.java'
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.StreamPi.Server.Connection;
-
-
-import com.StreamPi.Server.Client.Client;
-
-import java.net.SocketAddress;
-import java.util.ArrayList;
-
-public class ClientConnections {
-
- private ArrayList<ClientConnection> connections;
-
- private static ClientConnections instance = null;
-
- private ClientConnections()
- {
- connections = new ArrayList<>();
- }
-
- public static synchronized ClientConnections getInstance()
- {
- if(instance == null)
- {
- instance = new ClientConnections();
- }
-
- return instance;
- }
-
- public ArrayList<ClientConnection> getConnections()
- {
- return connections;
- }
-
- public void clearAllConnections()
- {
- connections.clear(); // NOT RECOMMENDED TO USE CARELESSLY
- }
-
- public void addConnection(ClientConnection connection)
- {
- connections.add(connection);
- }
-
- public void removeConnection(ClientConnection clientConnection)
- {
- System.out.println(connections.remove(clientConnection)+" 22222222222222222222222222222222222222222");
- }
-
- public void disconnectAll()
- {
- new Thread(()->{
- for(ClientConnection clientConnection : connections)
- {
- clientConnection.exit();
- }
-
- clearAllConnections();
- }).start();
- }
-
- public ClientConnection getClientConnectionBySocketAddress(SocketAddress socketAddress)
- {
- for(ClientConnection clientConnection : connections)
- {
- if(clientConnection.getClient().getRemoteSocketAddress().equals(socketAddress))
- return clientConnection;
- }
-
- return null;
- }
-}
\ No newline at end of file
--- 'a/src/main/java/com/StreamPi/Server/Connection/ConnectionService.java'
+++ /dev/null
@@ -1,345 +0,0 @@
-/*package com.StreamPi.Server.Connection;
-
-import com.StreamPi.ActionAPI.Action.Action;
-import com.StreamPi.ActionAPI.Action.ActionType;
-import com.StreamPi.ActionAPI.Action.Location;
-import com.StreamPi.ActionAPI.ActionProperty.ClientProperties;
-import com.StreamPi.ActionAPI.NormalAction.NormalAction;
-import com.StreamPi.CommAPI.ConnectionGrpc;
-import com.StreamPi.CommAPI.ServerGRPC;
-import com.StreamPi.Server.Action.NormalActionPlugins;
-import com.StreamPi.Server.Client.Client;
-import com.StreamPi.Server.Client.ClientProfile;
-import com.StreamPi.Server.Info.ServerInfo;
-import com.StreamPi.Util.Exception.MinorException;
-import com.StreamPi.Util.Exception.SevereException;
-import com.StreamPi.Util.Exception.StreamPiException;
-import com.StreamPi.Util.Platform.Platform;
-import com.StreamPi.Util.Version.Version;
-import io.grpc.stub.StreamObserver;
-import javafx.concurrent.Task;
-import javafx.scene.control.Alert;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-public class ConnectionService extends ConnectionGrpc.ConnectionImplBase {
-
- private Client client = null;
- private Logger logger;
-
- ServerListener serverListener;
-
- final HashMap<String, Boolean> actionStatuses;
-
- public ConnectionService(ServerListener serverListener)
- {
- super();
-
- isDisconnect = false;
- disconnectMessage = "";
-
- logger = LoggerFactory.getLogger(ConnectionService.class);
- actionStatuses = new HashMap<>();
-
- this.serverListener = serverListener;
- }
-
-
- boolean isDisconnect;
- String disconnectMessage;
-
- public void disconnect()
- {
- disconnect("");
- }
-
- public void disconnect(String message)
- {
- if(!isDisconnect)
- {
- this.isDisconnect = true;
- this.disconnectMessage = message;
- }
- }
-
- @Override
- public void sendClientDetails(ServerGRPC.ClientDetails request, StreamObserver<ServerGRPC.Status> responseObserver) {
-
- Version clientVersion;
- Version commsAPIVersion;
- Version themeAPIVersion;
-
- try
- {
- clientVersion = new Version(request.getClientVersion());
- commsAPIVersion = new Version(request.getCommAPIVersion());
- themeAPIVersion = new Version(request.getThemeAPIVersion());
- }
- catch (MinorException e)
- {
- e.printStackTrace();
- serverListener.onRPCError(new MinorException("versions invalid. Check stacktrace"));
- disconnect();
- return;
- }
-
-
- String nickName = request.getNickName();
- Platform platform = Platform.valueOf(request.getPlatform().toString());
-
- client = new Client(clientVersion, commsAPIVersion, themeAPIVersion, nickName, platform, null);
-
- boolean sendActions = true;
-
- if(!commsAPIVersion.isEqual(ServerInfo.getInstance().getCommAPIVersion()))
- {
- sendActions = false;
- disconnect("Client CommAPI and Server CommAPI do not match!");
- }
-
- responseObserver.onNext(ServerGRPC.Status.newBuilder().setSendActions(sendActions).build());
-
- responseObserver.onCompleted();
- }
-
- @Override
- public StreamObserver<ServerGRPC.ClientProfile> sendClientProfiles(StreamObserver<ServerGRPC.Empty> responseObserver) {
-
- client.getProfiles().clear();
-
- ArrayList<String> notFoundActions = new ArrayList<>();
-
- return new StreamObserver<ServerGRPC.ClientProfile>() {
- @Override
- public void onNext(ServerGRPC.ClientProfile clientProfile) {
-
- String name = clientProfile.getName();
- String id = clientProfile.getId();
-
- int rows = clientProfile.getRows();
- int cols = clientProfile.getCols();
-
- int actionSize = clientProfile.getActionSize();
- int actionGap = clientProfile.getActionGap();
-
- ClientProfile finalClientProfile = new ClientProfile(name, id, rows, cols, actionSize, actionGap);
-
- ArrayList<Action> actions = new ArrayList<>();
-
- List<ServerGRPC.ClientAction> clientActions = clientProfile.getActionsList();
- for(ServerGRPC.ClientAction clientAction : clientActions)
- {
-
- String actionID = clientAction.getId();
- String actionName = clientAction.getActionName();
-
- boolean hasIcon = clientAction.getHasIcon();
-
- ActionType actionType = ActionType.valueOf(clientAction.getActionType().toString());
-
- Action action = new Action(actionID, actionType);
- action.setActionName(actionName);
-
- action.setHasIcon(hasIcon);
-
- int locationX = clientAction.getLocationX();
- int locationY = clientAction.getLocationY();
-
- action.setLocation(new Location(locationX, locationY));
-
- if(actionType == ActionType.NORMAL)
- {
- action.setModuleName(clientAction.getModuleName());
-
- ClientProperties properties = new ClientProperties();
-
- List<ServerGRPC.ClientProperty> clientProperties = clientAction.getClientPropertiesList();
-
- for(ServerGRPC.ClientProperty clientProperty : clientProperties)
- {
- String propertyName = clientProperty.getName();
- String propertyValue = clientProperty.getValue();
-
- properties.addProperty(propertyName, propertyValue);
- }
-
- action.setClientProperties(properties);
-
- boolean isFound = false;
- for(NormalAction normalAction : NormalActionPlugins.getInstance().getPlugins())
- {
- if(normalAction.getModuleName().equals(action.getModuleName()))
- {
- isFound = true;
-
- normalAction.setClientProperties(action.getClientProperties());
- normalAction.setActionName(action.getActionName());
- normalAction.setHasIcon(action.isHasIcon());
- normalAction.setID(action.getID());
- normalAction.setLocation(action.getLocation());
- normalAction.setInvalid(false);
-
- actions.add(normalAction);
-
- break;
- }
- }
-
- if(!isFound)
- {
- String aName = action.getModuleName();
-
- action.setInvalid(true);
-
- logger.warn("Action "+aName+" not found!");
- if(!notFoundActions.contains(aName))
- notFoundActions.add(aName);
-
- actions.add(action);
- }
- }
- }
-
- finalClientProfile.setActions(actions);
- client.addProfile(finalClientProfile);
-
-
- }
-
- @Override
- public void onError(Throwable throwable) {
- serverListener.onRPCError(new SevereException(throwable.getMessage()));
- }
-
- @Override
- public void onCompleted() {
-
- if(!notFoundActions.isEmpty())
- {
- StringBuilder all = new StringBuilder("Some actions cannot be edited/used because they are not installed on the server : ");
-
- for(String each : notFoundActions)
- {
- all.append("\n * ").append(each);
- }
-
- serverListener.onAlert("Warning",all.toString(), Alert.AlertType.WARNING);
- }
-
- responseObserver.onNext(ServerGRPC.Empty.newBuilder().build());
- responseObserver.onCompleted();
- }
- };
- }
-
- @Override
- public void actionClicked(ServerGRPC.ClickedActionID request, StreamObserver<ServerGRPC.Empty> responseObserver) {
- try
- {
- Action actionClicked = client.getProfileByID(request.getProfileID()).getActionByID(request.getId());
- new Thread(new Task<Void>() {
- @Override
- protected Void call()
- {
- try
- {
- synchronized (actionStatuses)
- {
- actionStatuses.put(request.getId(), serverListener.onActionClicked(actionClicked));
- }
- }
- catch (MinorException e)
- {
- serverListener.onRPCError(e);
- }
- return null;
- }
- }).start();
- }
- catch (MinorException e)
- {
- e.printStackTrace();
- }
- finally {
- responseObserver.onNext(ServerGRPC.Empty.newBuilder().build());
- responseObserver.onCompleted();
- }
- }
-
- @Override
- public StreamObserver<ServerGRPC.Empty> actionClickedStatus(StreamObserver<ServerGRPC.ActionStatus> responseObserver) {
- return new StreamObserver<ServerGRPC.Empty>() {
- @Override
- public void onNext(ServerGRPC.Empty empty) {
-
- }
-
- @Override
- public void onError(Throwable throwable) {
- serverListener.onRPCError(new StreamPiException(throwable.getMessage()));
- }
-
- @Override
- public void onCompleted() {
- String id = null;
- boolean success = false;
- synchronized (actionStatuses)
- {
- if(!actionStatuses.isEmpty())
- {
- for(String key : actionStatuses.keySet())
- {
- id = key;
- success = actionStatuses.get(id);
-
- System.out.println("SDSDSDASDASDXZXCZXCZXC");
- break;
- }
- }
- }
-
- if(id==null)
- {
- responseObserver.onNext(ServerGRPC.ActionStatus.newBuilder().build());
- }
- else
- responseObserver.onNext(ServerGRPC.ActionStatus.newBuilder()
- .setId(id)
- .setIsSuccess(success)
- .build());
-
- responseObserver.onCompleted();
- }
- };
- }
-
- @Override
- public StreamObserver<ServerGRPC.DisconnectMessage> disconnect(StreamObserver<ServerGRPC.DisconnectMessage> responseObserver) {
- return new StreamObserver<ServerGRPC.DisconnectMessage>() {
- @Override
- public void onNext(ServerGRPC.DisconnectMessage disconnectMessage) {
- if(disconnectMessage.getIsDisconnect())
- disconnect(disconnectMessage.getMessage());
- }
-
- @Override
- public void onError(Throwable throwable) {
- serverListener.onRPCError(new StreamPiException(throwable.getMessage()));
- }
-
- @Override
- public void onCompleted() {
- responseObserver.onNext(ServerGRPC.DisconnectMessage.newBuilder()
- .setIsDisconnect(isDisconnect)
- .setMessage(disconnectMessage)
- .build());
- responseObserver.onCompleted();
- }
- };
- }
-}
-*/
\ No newline at end of file
--- 'a/src/main/java/com/StreamPi/Server/Connection/MainServer.java'
+++ /dev/null
@@ -1,105 +0,0 @@
-package com.StreamPi.Server.Connection;
-
-import com.StreamPi.Server.Window.ExceptionAndAlertHandler;
-import com.StreamPi.Util.Exception.MinorException;
-import com.StreamPi.Util.Exception.SevereException;
-import javafx.concurrent.Task;
-
-import java.io.IOException;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.SocketException;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.logging.Logger;
-
-public class MainServer extends Thread{
- private ServerListener serverListener;
-
- private Logger logger = Logger.getLogger(MainServer.class.getName());
- private int port;
- private ServerSocket serverSocket = null;
- //private Server server;
-
-
- private AtomicBoolean stop = new AtomicBoolean(false);
-
- private ExceptionAndAlertHandler exceptionAndAlertHandler;
- public MainServer(ServerListener serverListener, ExceptionAndAlertHandler exceptionAndAlertHandler)
- {
- this.exceptionAndAlertHandler = exceptionAndAlertHandler;
- this.port = port;
- this.serverListener = serverListener;
- }
-
-
- public void setPort(int port) {
- this.port = port;
- }
-
- @Override
- public synchronized void start() {
- stop.set(false);
- super.start();
- }
-
- public void stopListeningForConnections()
- {
-
- /*if(server !=null)
- {
- if(!server.isShutdown())
- server.shutdown();
- }*/
-
- try
- {
- logger.info("Stopping listening for connections ...");
- if(serverSocket!=null)
- if(!serverSocket.isClosed())
- serverSocket.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- finally {
- logger.info("... Done!");
- }
- stop.set(true);
- }
-
- @Override
- public void run() {
- logger.warning("Starting main server on port "+port+" ...");
-
- try {
-
- logger.info("Starting server on port "+port+" ...");
- /*Server server = ServerBuilder.forPort(port)
- .addService(new ConnectionService(serverListener))
- .build();
-
- server.start();
- logger.info("... Done!");*/
-
- serverSocket = new ServerSocket(port);
-
- while(!stop.get())
- {
- Socket s = serverSocket.accept();
- ClientConnections.getInstance().addConnection(new ClientConnection(s, serverListener, exceptionAndAlertHandler));
-
- logger.info("New Client connected ("+s.getRemoteSocketAddress()+") !");
- }
-
- }
- catch (SocketException e)
- {
- logger.info("Main Server stopped accepting calls ...");
- e.printStackTrace(); //more likely stopped listening;
- } catch (IOException e) {
- exceptionAndAlertHandler.handleSevereException(new SevereException("MainServer IO Exception occurred!"));
- e.printStackTrace();
- }
- }
-
-
-}
--- 'a/src/main/java/com/StreamPi/Server/Connection/ServerListener.java'
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.StreamPi.Server.Connection;
-
-import com.StreamPi.ActionAPI.Action.Action;
-import com.StreamPi.ActionAPI.NormalAction.NormalAction;
-import com.StreamPi.Server.Client.Client;
-import com.StreamPi.Util.Exception.MinorException;
-import com.StreamPi.Util.Exception.SevereException;
-import com.StreamPi.Util.Exception.StreamPiException;
-import javafx.scene.control.Alert;
-
-import java.net.Socket;
-
-public interface ServerListener {
- boolean onNormalActionClicked(NormalAction action);
-
- void clearTemp();
-
- void init();
-
- void othInit();
-}
--- 'a/src/main/java/com/StreamPi/Server/Controller/Controller.java'
+++ /dev/null
@@ -1,540 +0,0 @@
-package com.StreamPi.Server.Controller;
-
-import com.StreamPi.ActionAPI.Action.ServerConnection;
-import com.StreamPi.ActionAPI.Action.PropertySaver;
-import com.StreamPi.ActionAPI.NormalAction.NormalAction;
-import com.StreamPi.Server.Main;
-import com.StreamPi.Server.Action.NormalActionPlugins;
-import com.StreamPi.Server.Connection.ClientConnections;
-import com.StreamPi.Server.Connection.MainServer;
-import com.StreamPi.Server.IO.Config;
-import com.StreamPi.Server.Info.ServerInfo;
-import com.StreamPi.Server.Window.Base;
-import com.StreamPi.Server.Window.Dashboard.DonatePopupContent;
-import com.StreamPi.Server.Window.FirstTimeUse.FirstTimeUse;
-import com.StreamPi.Util.Alert.StreamPiAlert;
-import com.StreamPi.Util.Alert.StreamPiAlertListener;
-import com.StreamPi.Util.Alert.StreamPiAlertType;
-import com.StreamPi.Util.Exception.MinorException;
-import com.StreamPi.Util.Exception.SevereException;
-import com.StreamPi.Util.IOHelper.IOHelper;
-
-import javafx.animation.Interpolator;
-import javafx.animation.KeyFrame;
-import javafx.animation.KeyValue;
-import javafx.animation.Timeline;
-import javafx.application.Platform;
-import javafx.concurrent.Task;
-import javafx.scene.Node;
-import javafx.scene.Scene;
-import javafx.stage.Modality;
-import javafx.stage.Stage;
-import javafx.stage.WindowEvent;
-import java.awt.SystemTray;
-import javafx.util.Duration;
-import java.awt.Toolkit;
-import java.awt.TrayIcon;
-import java.awt.PopupMenu;
-import java.awt.MenuItem;
-
-import java.io.File;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.Random;
-import java.util.logging.Level;
-
-public class Controller extends Base implements PropertySaver, ServerConnection
-{
- MainServer mainServer;
-
- final SystemTray systemTray;
-
- public void setupDashWindow() throws SevereException
- {
- try
- {
- getStage().setTitle("Stream-Pi Server - "+InetAddress.getLocalHost().getCanonicalHostName()+":"+Config.getInstance().getPort()); //Sets title
- getStage().setOnCloseRequest(this::onCloseRequest);
- }
- catch (UnknownHostException e)
- {
- e.printStackTrace();
- throw new SevereException(e.getMessage());
- }
- }
-
- private void checkPrePathDirectory() throws SevereException
- {
- try {
- File filex = new File(ServerInfo.getInstance().getPrePath());
-
- System.out.println("SAX : "+filex.exists());
- if(!filex.exists())
- {
- filex.mkdirs();
- IOHelper.unzip(Main.class.getResourceAsStream("Default.obj"), ServerInfo.getInstance().getPrePath());
- }
- }
- catch (Exception e)
- {
- e.printStackTrace();
- throw new SevereException(e.getMessage());
- }
- }
-
- @Override
- public void init()
- {
- try {
- checkPrePathDirectory();
-
- initBase();
- setupDashWindow();
-
-
- setupSettingsWindowsAnimations();
-
- NormalActionPlugins.getInstance().setPropertySaver(this);
- NormalActionPlugins.getInstance().setServerConnection(this);
-
-
- getDashboardPane().getPluginsPane().getSettingsButton().setOnAction(event -> {
- openSettingsTimeLine.play();
- });
-
- getSettingsPane().getCloseButton().setOnAction(event -> {
- closeSettingsTimeLine.play();
- });
-
- getSettingsPane().getThemesSettings().setController(this);
-
-
- mainServer = new MainServer(this, this);
-
-
- if(getConfig().isFirstTimeUse())
- {
- Stage stage = new Stage();
- Scene s = new Scene(new FirstTimeUse(this, this), 512, 300);
- stage.setResizable(false);
- stage.setScene(s);
- stage.setTitle("Stream-Pi Server Setup");
- stage.initModality(Modality.APPLICATION_MODAL);
- stage.setOnCloseRequest(event->Platform.exit());
- stage.show();
- }
- else
- {
- if(getConfig().isAllowDonatePopup())
- {
- if(new Random().nextInt(5) == 3)
- new DonatePopupContent(getHostServices(), this).show();
- }
-
- othInit();
- }
-
- }
- catch (SevereException e)
- {
- handleSevereException(e);
- }
- }
-
- @Override
- public void othInit()
- {
- try
- {
- if(ServerInfo.getInstance().isStartMinimised())
- minimiseApp();
- else
- getStage().show();
- }
- catch(MinorException e)
- {
- handleMinorException(e);
- }
-
- new Thread(new Task<Void>() {
- @Override
- protected Void call()
- {
- try
- {
- getSettingsPane().getGeneralSettings().loadDataFromConfig();
-
- //themes
- getSettingsPane().getThemesSettings().setThemes(getThemes());
- getSettingsPane().getThemesSettings().setCurrentThemeFullName(getCurrentTheme().getFullName());
- getSettingsPane().getThemesSettings().loadThemes();
-
- //clients
- getSettingsPane().getClientsSettings().loadData();
-
- try
- {
-
- //Plugins
- Platform.runLater(()->{
- getDashboardPane().getPluginsPane().clearData();
- getDashboardPane().getPluginsPane().loadOtherActions();
- });
-
- NormalActionPlugins.setPluginsLocation(getConfig().getPluginsPath());
- NormalActionPlugins.getInstance().init();
-
- Platform.runLater(()->getDashboardPane().getPluginsPane().loadData());
-
- getSettingsPane().getPluginsSettings().loadPlugins();
- }
- catch (MinorException e)
- {
- getSettingsPane().getPluginsSettings().showPluginInitError();
- handleMinorException(e);
- }
-
- //Server
- mainServer.setPort(getConfig().getPort());
- mainServer.start();
-
- }
- catch (SevereException e)
- {
- handleSevereException(e);
- }
- return null;
- }
- }).start();
- }
-
- private void setupSettingsWindowsAnimations()
- {
- Node settingsNode = getSettingsPane();
- Node dashboardNode = getDashboardPane();
-
- openSettingsTimeLine = new Timeline();
- openSettingsTimeLine.setCycleCount(1);
-
-
- openSettingsTimeLine.getKeyFrames().addAll(
- new KeyFrame(Duration.millis(0.0D),
- new KeyValue(settingsNode.opacityProperty(),
- 0.0D, Interpolator.EASE_IN),
- new KeyValue(settingsNode.scaleXProperty(),
- 1.1D, Interpolator.EASE_IN),
- new KeyValue(settingsNode.scaleYProperty(),
- 1.1D, Interpolator.EASE_IN),
- new KeyValue(settingsNode.scaleZProperty(),
- 1.1D, Interpolator.EASE_IN)),
- new KeyFrame(Duration.millis(90.0D),
- new KeyValue(settingsNode.opacityProperty(),
- 1.0D, Interpolator.LINEAR),
- new KeyValue(settingsNode.scaleXProperty(),
- 1.0D, Interpolator.LINEAR),
- new KeyValue(settingsNode.scaleYProperty(),
- 1.0D, Interpolator.LINEAR),
- new KeyValue(settingsNode.scaleZProperty(),
- 1.0D, Interpolator.LINEAR)),
-
-
- new KeyFrame(Duration.millis(0.0D),
- new KeyValue(dashboardNode.opacityProperty(),
- 1.0D, Interpolator.LINEAR),
- new KeyValue(dashboardNode.scaleXProperty(),
- 1.0D, Interpolator.LINEAR),
- new KeyValue(dashboardNode.scaleYProperty(),
- 1.0D, Interpolator.LINEAR),
- new KeyValue(dashboardNode.scaleZProperty(),
- 1.0D, Interpolator.LINEAR)),
- new KeyFrame(Duration.millis(90.0D),
- new KeyValue(dashboardNode.opacityProperty(),
- 0.0D, Interpolator.LINEAR),
- new KeyValue(dashboardNode.scaleXProperty(),
- 0.9D, Interpolator.LINEAR),
- new KeyValue(dashboardNode.scaleYProperty(),
- 0.9D, Interpolator.LINEAR),
- new KeyValue(dashboardNode.scaleZProperty(),
- 0.9D, Interpolator.LINEAR))
- );
-
- openSettingsTimeLine.setOnFinished(event1 -> {
- settingsNode.toFront();
- });
-
-
- closeSettingsTimeLine = new Timeline();
- closeSettingsTimeLine.setCycleCount(1);
-
- closeSettingsTimeLine.getKeyFrames().addAll(
-
- new KeyFrame(Duration.millis(0.0D),
- new KeyValue(settingsNode.opacityProperty(),
- 1.0D, Interpolator.LINEAR),
- new KeyValue(settingsNode.scaleXProperty(),
- 1.0D, Interpolator.LINEAR),
- new KeyValue(settingsNode.scaleYProperty(),
- 1.0D, Interpolator.LINEAR),
- new KeyValue(settingsNode.scaleZProperty(),
- 1.0D, Interpolator.LINEAR)),
- new KeyFrame(Duration.millis(90.0D),
- new KeyValue(settingsNode.opacityProperty(),
- 0.0D, Interpolator.LINEAR),
- new KeyValue(settingsNode.scaleXProperty(),
- 1.1D, Interpolator.LINEAR),
- new KeyValue(settingsNode.scaleYProperty(),
- 1.1D, Interpolator.LINEAR),
- new KeyValue(settingsNode.scaleZProperty(),
- 1.1D, Interpolator.LINEAR)),
-
- new KeyFrame(Duration.millis(0.0D),
- new KeyValue(dashboardNode.opacityProperty(),
- 0.0D, Interpolator.LINEAR),
- new KeyValue(dashboardNode.scaleXProperty(),
- 0.9D, Interpolator.LINEAR),
- new KeyValue(dashboardNode.scaleYProperty(),
- 0.9D, Interpolator.LINEAR),
- new KeyValue(dashboardNode.scaleZProperty(),
- 0.9D, Interpolator.LINEAR)),
- new KeyFrame(Duration.millis(90.0D),
- new KeyValue(dashboardNode.opacityProperty(),
- 1.0D, Interpolator.LINEAR),
- new KeyValue(dashboardNode.scaleXProperty(),
- 1.0D, Interpolator.LINEAR),
- new KeyValue(dashboardNode.scaleYProperty(),
- 1.0D, Interpolator.LINEAR),
- new KeyValue(dashboardNode.scaleZProperty(),
- 1.0D, Interpolator.LINEAR))
-
- );
-
- closeSettingsTimeLine.setOnFinished(event1 -> {
- dashboardNode.toFront();
- new Thread(new Task<Void>() {
- @Override
- protected Void call() {
- try {
- getSettingsPane().getClientsSettings().loadData();
-
- getSettingsPane().getGeneralSettings().loadDataFromConfig();
- getSettingsPane().getPluginsSettings().loadPlugins();
-
- getSettingsPane().getThemesSettings().setThemes(getThemes());
- getSettingsPane().getThemesSettings().setCurrentThemeFullName(getCurrentTheme().getFullName());
- getSettingsPane().getThemesSettings().loadThemes();
-
- getSettingsPane().setDefaultTabToGeneral();
- }
- catch (SevereException e)
- {
- handleSevereException(e);
- }
- catch (MinorException e)
- {
- handleMinorException(e);
- }
- return null;
- }
- }).start();
- });
- }
-
- private Timeline openSettingsTimeLine;
- private Timeline closeSettingsTimeLine;
-
-
- public Controller(){
- systemTray = SystemTray.getSystemTray();
- mainServer = null;
- }
-
- public void onCloseRequest(WindowEvent event)
- {
- try
- {
- if(Config.getInstance().getCloseOnX())
- {
- getConfig().setStartupWindowSize(
- getWidth(),
- getHeight()
- );
- getConfig().save();
- onQuitApp();
- NormalActionPlugins.getInstance().shutDownActions();
- Platform.exit();
- }
- else
- {
- minimiseApp();
- event.consume();
- }
- }
- catch (SevereException e)
- {
- handleSevereException(e);
- }
- catch (MinorException e)
- {
- handleMinorException(e);
- }
- finally
- {
- closeLogger();
- }
- }
-
- public void onQuitApp()
- {
- if(mainServer!=null)
- mainServer.stopListeningForConnections();
-
- ClientConnections.getInstance().disconnectAll();
-
- getLogger().info("Shutting down ...");
- }
-
- public void minimiseApp() throws MinorException
- {
- try
- {
-
- if(SystemTray.isSupported())
- {
- if(getTrayIcon() == null)
- initIconTray();
-
- systemTray.add(getTrayIcon());
- //getStage().setIconified(true);
- getStage().hide();
- }
- else
- {
- new StreamPiAlert("System Tray Error", "Your System does not support System Tray", StreamPiAlertType.ERROR).show();
- }
- }
- catch(Exception e)
- {
- throw new MinorException(e.getMessage());
- }
- }
-
- public void initIconTray()
- {
-
- Platform.setImplicitExit(false);
-
- PopupMenu popup = new PopupMenu();
-
- MenuItem showItem = new MenuItem("Show");
- showItem.addActionListener(l->{
- systemTray.remove(getTrayIcon());
- Platform.runLater(()->{
- //getStage().setIconified(false);
- getStage().show();
- });
- });
-
- MenuItem exitItem = new MenuItem("Exit");
- exitItem.addActionListener(l->{
- systemTray.remove(getTrayIcon());
- onQuitApp();
- Platform.exit();
- });
-
- popup.add(showItem);
- popup.addSeparator();
- popup.add(exitItem);
-
- TrayIcon trayIcon = new TrayIcon(
- Toolkit.getDefaultToolkit().getImage(Main.class.getResource("app_icon.png")),
- "Stream-Pi Server",
- popup
- );
-
- trayIcon.setImageAutoSize(true);
-
- this.trayIcon = trayIcon;
- }
-
- private TrayIcon trayIcon = null;
-
- public TrayIcon getTrayIcon()
- {
- return trayIcon;
- }
-
- @Override
- public void handleMinorException(MinorException e) {
- getLogger().log(Level.SEVERE, e.getMessage());
- e.printStackTrace();
-
- Platform.runLater(()-> new StreamPiAlert(e.getTitle(), e.getShortMessage(), StreamPiAlertType.WARNING).show());
- }
-
- @Override
- public void handleSevereException(SevereException e) {
- getLogger().log(Level.SEVERE, e.getMessage());
- e.printStackTrace();
-
- Platform.runLater(()->{
- StreamPiAlert alert = new StreamPiAlert(e.getTitle(), e.getShortMessage(), StreamPiAlertType.ERROR);
-
- alert.setOnClicked(new StreamPiAlertListener()
- {
- @Override
- public void onClick(String txt)
- {
- onQuitApp();
- Platform.exit();
- }
- });
-
- alert.show();
- });
- }
-
- @Override
- public synchronized boolean onNormalActionClicked(NormalAction action) {
- try{
- getLogger().info("Action "+action.getID()+" clicked!");
-
- action.onActionClicked();
- return true;
- }
- catch (Exception e)
- {
- handleMinorException(new MinorException(
- "Action Execution Failed!",
- "Error running Action at ["+action.getLocation().getRow()+","+action.getLocation().getCol()+"] ("+action.getDisplayText()+")\n"+
- "Check stacktrace/log to know what exactly happened\n\nMessage : \n"+e.getMessage() )
- );
- return false;
- }
- }
-
- @Override
- public void clearTemp() {
- Platform.runLater(() -> {
- getDashboardPane().getClientDetailsPane().refresh();
- getDashboardPane().getActionGridPane().clear();
- getDashboardPane().getActionDetailsPane().clear();
- getSettingsPane().getClientsSettings().loadData();
- });
- }
-
- @Override
- public void saveServerProperties() {
- try {
- NormalActionPlugins.getInstance().saveServerSettings();
- getSettingsPane().getPluginsSettings().loadPlugins();
- } catch (MinorException e) {
- e.printStackTrace();
- handleMinorException(e);
- }
- }
-
- @Override
- public com.StreamPi.Util.Platform.Platform getPlatform() {
- return ServerInfo.getInstance().getPlatformType();
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/IO/Config.java'
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
-Config.java
-
-Contributor(s) : Debayan Sutradhar (@rnayabed)
-
-handler for config.xml
- */
-
-package com.StreamPi.Server.IO;
-
-import java.io.File;
-import java.util.logging.Logger;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.transform.Result;
-import javax.xml.transform.Source;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
-import com.StreamPi.Server.Info.ServerInfo;
-import com.StreamPi.Util.Exception.SevereException;
-import com.StreamPi.Util.XMLConfigHelper.XMLConfigHelper;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-public class Config {
-
- private static Config instance = null;
-
- private final File configFile;
-
- private Document document;
-
- private Config() throws SevereException {
- try {
- configFile = new File(ServerInfo.getInstance().getPrePath()+"config.xml");
- DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
- DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
- document = docBuilder.parse(configFile);
- } catch (Exception e) {
- e.printStackTrace();
- throw new SevereException("Config", "unable to read config.xml");
- }
- }
-
- public static synchronized Config getInstance() throws SevereException
- {
- if(instance == null)
- instance = new Config();
-
- return instance;
- }
-
- Logger logger = Logger.getLogger(Config.class.getName());
-
- public void save() throws SevereException {
- try {
- logger.info("Saving config ...");
- Transformer transformer = TransformerFactory.newInstance().newTransformer();
- Result output = new StreamResult(configFile);
- Source input = new DOMSource(document);
-
- transformer.transform(input, output);
- logger.info("... Done!");
- } catch (Exception e) {
- throw new SevereException("Config", "unable to save config.xml");
- }
- }
-
-
- //Getters
-
- //comms
- private Element getCommsElement()
- {
- return (Element) document.getElementsByTagName("comms").item(0);
- }
-
- public String getServerName()
- {
- return XMLConfigHelper.getStringProperty(getCommsElement(), "name",
- getDefaultServerName(), false, true, document, configFile);
- }
-
- public int getPort()
- {
- return XMLConfigHelper.getIntProperty(getCommsElement(), "port",
- getDefaultPort(), false, true, document, configFile);
- }
-
- //default getters
- public String getDefaultServerName()
- {
- return "StreamPi Server";
- }
-
- public int getDefaultPort()
- {
- return 2004;
- }
-
- private Element getServerElement()
- {
- return (Element) document.getElementsByTagName("server").item(0);
- }
-
-
- //server
-
- private Element getActionGridElement()
- {
- return (Element) getServerElement().getElementsByTagName("action-grid").item(0);
- }
- public int getActionGridActionGap()
- {
- return XMLConfigHelper.getIntProperty(getActionGridElement(), "gap",
- getDefaultActionGridActionGap(), false, true, document, configFile);
- }
-
- public int getActionGridActionSize()
- {
- return XMLConfigHelper.getIntProperty(getActionGridElement(), "size",
- getDefaultActionGridSize(), false, true, document, configFile);
- }
-
-
- public String getCurrentThemeFullName()
- {
- return XMLConfigHelper.getStringProperty(getServerElement(), "current-theme-full-name",
- getDefaultCurrentThemeFullName(), false, true, document, configFile);
- }
-
- public String getThemesPath()
- {
- return XMLConfigHelper.getStringProperty(getServerElement(), "themes-path",
- getDefaultThemesPath(), false, true, document, configFile);
- }
-
-
- public String getPluginsPath()
- {
- return XMLConfigHelper.getStringProperty(getServerElement(), "plugins-path",
- getDefaultPluginsPath(), false, true, document, configFile);
- }
-
- //default getters
- public String getDefaultCurrentThemeFullName()
- {
- return "com.StreamPi.DefaultLight";
- }
-
- public String getDefaultThemesPath()
- {
- return "Themes/";
- }
-
- public String getDefaultPluginsPath()
- {
- return "Plugins/";
- }
-
-
- //server > startup-window-size
-
- private Element getStartupWindowSizeElement()
- {
- return (Element) getServerElement().getElementsByTagName("startup-window-size").item(0);
- }
-
- public double getStartupWindowWidth()
- {
- return XMLConfigHelper.getDoubleProperty(getStartupWindowSizeElement(), "width",
- getDefaultStartupWindowWidth(), false, true, document, configFile);
- }
-
- public double getStartupWindowHeight()
- {
- return XMLConfigHelper.getDoubleProperty(getStartupWindowSizeElement(), "height",
- getDefaultStartupWindowHeight(), false, true, document, configFile);
- }
-
- //default getters
- public int getDefaultStartupWindowWidth()
- {
- return 1024;
- }
-
- public int getDefaultStartupWindowHeight()
- {
- return 768;
- }
-
-
- //others
- private Element getOthersElement()
- {
- return (Element) document.getElementsByTagName("others").item(0);
- }
-
- public boolean getStartOnBoot()
- {
- return XMLConfigHelper.getBooleanProperty(getOthersElement(), "start-on-boot",
- getDefaultStartOnBoot(), false, true, document, configFile);
- }
-
- public boolean getCloseOnX()
- {
- return XMLConfigHelper.getBooleanProperty(getOthersElement(), "close-on-x",
- getDefaultCloseOnX(), false, true, document, configFile);
- }
-
- public boolean isFirstTimeUse()
- {
- return XMLConfigHelper.getBooleanProperty(getOthersElement(), "first-time-use", true, false, true, document, configFile);
- }
-
- public boolean isAllowDonatePopup()
- {
- return XMLConfigHelper.getBooleanProperty(getOthersElement(), "allow-donate-popup", true, false, true, document, configFile);
- }
-
- //default getters
- public boolean getDefaultStartOnBoot()
- {
- return false;
- }
-
- public boolean getDefaultCloseOnX()
- {
- return false;
- }
-
-
- //Setters
-
- //comms
- public void setServerName(String name)
- {
- getCommsElement().getElementsByTagName("name").item(0).setTextContent(name);
- }
-
- public void setServerPort(int port)
- {
- getCommsElement().getElementsByTagName("port").item(0).setTextContent(port+"");
- }
-
- //server
-
- public int getDefaultActionGridActionGap()
- {
- return 5;
- }
-
- public int getDefaultActionGridSize()
- {
- return 100;
- }
-
- public void setActionGridSize(int size)
- {
- getActionGridElement().getElementsByTagName("size").item(0).setTextContent(size+"");
- }
-
- public void setActionGridGap(int size)
- {
- getActionGridElement().getElementsByTagName("gap").item(0).setTextContent(size+"");
- }
-
- public void setPluginsPath(String path)
- {
- getServerElement().getElementsByTagName("plugins-path").item(0).setTextContent(path);
- }
-
- public void setThemesPath(String path)
- {
- getServerElement().getElementsByTagName("themes-path").item(0).setTextContent(path);
- }
-
- public void setCurrentThemeFullName(String themeName)
- {
- getServerElement().getElementsByTagName("current-theme-full-name").item(0).setTextContent(themeName);
- }
-
- //server > startup-window-size
- public void setStartupWindowSize(double width, double height)
- {
- setStartupWindowWidth(width);
- setStartupWindowHeight(height);
- }
-
- public void setStartupWindowWidth(double width)
- {
- getStartupWindowSizeElement().getElementsByTagName("width").item(0).setTextContent(width+"");
- }
-
- public void setStartupWindowHeight(double height)
- {
- getStartupWindowSizeElement().getElementsByTagName("height").item(0).setTextContent(height+"");
- }
-
- //others
- public void setStartupOnBoot(boolean value)
- {
- getOthersElement().getElementsByTagName("start-on-boot").item(0).setTextContent(value+"");
- }
-
- public void setCloseOnX(boolean value)
- {
- getOthersElement().getElementsByTagName("close-on-x").item(0).setTextContent(value+"");
- }
-
- public void setFirstTimeUse(boolean value)
- {
- getOthersElement().getElementsByTagName("first-time-use").item(0).setTextContent(value+"");
- }
-
- public void setAllowDonatePopup(boolean value)
- {
- getOthersElement().getElementsByTagName("allow-donate-popup").item(0).setTextContent(value+"");
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/Info/License.java'
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macropad
-Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Written by : Debayan Sutradhar (rnayabed)
-*/
-
-package com.StreamPi.Server.Info;
-
-public class License {
- /**
- * @return Formatted String containing the Stream-Pi License an also licenses of other opensource libraries used.
- */
- public static String getLicense()
- {
- return "Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macro Pad\n" +
- "Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)\n" +
- "\n" +
- "This program is free software: you can redistribute it and/or modify\n" +
- "it under the terms of the GNU General Public License as published by\n" +
- "the Free Software Foundation, either version 3 of the License, or\n" +
- "(at your option) any later version.\n" +
- "\n" +
- "This program is distributed in the hope that it will be useful,\n" +
- "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +
- "GNU General Public License for more details.\n" +
- "\n\n"+
- "Opensource Libraries used :\n"+
- "1. JavaFX - GNU General Public License with Classpath Exception\nhttp://openjdk.java.net/legal/gplv2+ce.html\n\n"+
- "2. JSON - The JSON License\nhttps://www.json.org/license.html\n\n"+
- "3. Ikonli - Apache License\nhttps://github.com/kordamp/ikonli/blob/master/LICENSE\n\n";
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/Info/ServerInfo.java'
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
-ServerInfo.java
-
-Stores basic information about the server - name, platform type
-
-Contributors: Debayan Sutradhar (@dubbadhar)
- */
-
-package com.StreamPi.Server.Info;
-
-import com.StreamPi.Util.Exception.MinorException;
-import com.StreamPi.Util.Platform.Platform;
-import com.StreamPi.Util.Platform.ReleaseStatus;
-import com.StreamPi.Util.Version.Version;
-
-public class ServerInfo {
- private Version version;
- private final ReleaseStatus releaseStatus;
- private final Platform platformType;
-
- private String prePath;
-
- private Version minThemeSupportVersion;
- private Version minPluginSupportVersion;
- private Version commStandardVersion;
-
- private static ServerInfo instance = null;
-
- private String runnerFileName = null;
- private boolean startMinimised = false;
-
- private ServerInfo(){
- version = new Version(1,0,0);
- minThemeSupportVersion = new Version(1,0,0);
- minPluginSupportVersion = new Version(1,0,0);
- commStandardVersion = new Version(1,0,0);
-
- releaseStatus = ReleaseStatus.EA;
- prePath = "data/";
-
- String osName = System.getProperty("os.name").toLowerCase();
-
- if(osName.contains("windows"))
- platformType = Platform.WINDOWS;
- else if (osName.contains("linux"))
- platformType = Platform.LINUX;
- else if (osName.contains("mac"))
- platformType = Platform.MAC;
- else
- platformType = Platform.UNKNOWN;
-
-
- }
-
-
- public String getPrePath() {
- return prePath;
- }
-
- public void setStartMinimised(boolean startMinimised)
- {
- this.startMinimised = startMinimised;
- }
-
- public boolean isStartMinimised()
- {
- return startMinimised;
- }
-
- public void setRunnerFileName(String runnerFileName)
- {
- this.runnerFileName = runnerFileName;
- }
-
- public String getRunnerFileName()
- {
- return runnerFileName;
- }
-
- public static synchronized ServerInfo getInstance(){
- if(instance == null)
- {
- instance = new ServerInfo();
- }
-
- return instance;
- }
-
-
- public Platform getPlatformType()
- {
- return platformType;
- }
-
- public Version getVersion() {
- return version;
- }
-
- public ReleaseStatus getReleaseStatus()
- {
- return releaseStatus;
- }
-
- public Version getMinThemeSupportVersion()
- {
- return minThemeSupportVersion;
- }
-
- public Version getMinPluginSupportVersion()
- {
- return minPluginSupportVersion;
- }
-
- public Version getCommStandardVersion()
- {
- return commStandardVersion;
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/Main.java'
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macropad
-Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Written by : Debayan Sutradhar (rnayabed)
-*/
-
-
-package com.StreamPi.Server;
-
-import com.StreamPi.Server.Controller.Controller;
-import com.StreamPi.Server.Info.ServerInfo;
-
-import javafx.application.Application;
-import javafx.scene.Scene;
-import javafx.stage.Stage;
-
-public class Main extends Application {
-
- /**
- * First method to be called
- * This method first parses all the available command line arguments passed.
- * Then a new instance of Controller is created, and then initialised.
- */
- public void start(Stage stage) {
-
- for(String eachArg : getParameters().getRaw())
- {
- String[] r = eachArg.split("=");
- if(r[0].equals("-DStreamPi.startupRunnerFileName"))
- ServerInfo.getInstance().setRunnerFileName(r[1]);
- else if(r[0].equals("-DStreamPi.startupMode"))
- ServerInfo.getInstance().setStartMinimised(r[1].equals("min"));
- }
-
-
- Controller d = new Controller();
- Scene s = new Scene(d);
- stage.setScene(s);
- d.setHostServices(getHostServices());
- d.init();
- }
-
- /**
- * This is a fallback. Called in some JVMs.
- * This method just sends the command line arguments to JavaFX Application
- */
- public static void main(String[] args)
- {
-
- launch(args);
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/UIPropertyBox/UIPropertyBox.java'
+++ /dev/null
@@ -1,81 +0,0 @@
-package com.StreamPi.Server.UIPropertyBox;
-
-import com.StreamPi.ActionAPI.ActionProperty.Property.ControlType;
-import com.StreamPi.ActionAPI.ActionProperty.Property.Type;
-import javafx.scene.Node;
-import javafx.scene.control.ComboBox;
-import javafx.scene.control.Slider;
-import javafx.scene.control.TextField;
-import javafx.scene.control.ToggleButton;
-
-public class UIPropertyBox
-{
- private Node controlNode;
- private boolean canBeBlank;
- private String displayName;
-
- public String getDisplayName() {
- return displayName;
- }
-
- public boolean isCanBeBlank() {
- return canBeBlank;
- }
-
- private int index;
-
- private ControlType controlType;
- private Type type;
-
- public UIPropertyBox(int index, String displayName, Node controlNode, ControlType controlType, Type type, boolean canBeBlank)
- {
- this.index = index;
- this.displayName = displayName;
- this.controlNode = controlNode;
- this.controlType = controlType;
- this.type = type;
- this.canBeBlank = canBeBlank;
- }
-
- public ControlType getControlType()
- {
- return controlType;
- }
-
- public Node getControlNode()
- {
- return controlNode;
- }
-
- public int getIndex() {
- return index;
- }
-
- public Type getType()
- {
- return type;
- }
-
- public String getRawValue()
- {
- String rawValue = null;
-
- if (controlType == ControlType.TEXT_FIELD)
- rawValue = ((TextField) controlNode).getText();
- else if (controlType == ControlType.COMBO_BOX)
- rawValue = ((ComboBox<String>) controlNode).getSelectionModel().getSelectedIndex() + "";
- else if (controlType == ControlType.SLIDER_DOUBLE)
- rawValue = ((Slider) controlNode).getValue() + "";
- else if (controlType == ControlType.SLIDER_INTEGER)
- rawValue = Math.round(((Slider) controlNode).getValue()) + "";
- else if (controlType == ControlType.TOGGLE) {
- ToggleButton toggleButton = ((ToggleButton) controlNode);
- if (toggleButton.isSelected())
- rawValue = "true";
- else
- rawValue = "false";
- }
-
- return rawValue;
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/Base.java'
+++ /dev/null
@@ -1,276 +0,0 @@
-package com.StreamPi.Server.Window;
-
-import com.StreamPi.Server.Connection.ServerListener;
-import com.StreamPi.Server.IO.Config;
-import com.StreamPi.Server.Info.ServerInfo;
-import com.StreamPi.Server.Main;
-import com.StreamPi.Server.Window.Dashboard.*;
-import com.StreamPi.Server.Window.Settings.SettingsBase;
-import com.StreamPi.ThemeAPI.Theme;
-import com.StreamPi.ThemeAPI.Themes;
-import com.StreamPi.Util.Alert.StreamPiAlert;
-import com.StreamPi.Util.Exception.MinorException;
-import com.StreamPi.Util.Exception.SevereException;
-import com.StreamPi.Util.LoggerHelper.StreamPiLogFileHandler;
-
-import javafx.application.HostServices;
-import javafx.scene.image.Image;
-import javafx.scene.layout.StackPane;
-import javafx.scene.text.Font;
-import javafx.stage.Stage;
-import java.awt.SystemTray;
-import java.awt.Toolkit;
-import java.awt.TrayIcon;
-import java.io.IOException;
-import java.util.logging.LogManager;
-import java.util.logging.Logger;
-import java.awt.PopupMenu;
-import java.awt.MenuItem;
-
-public abstract class Base extends StackPane implements ExceptionAndAlertHandler, ServerListener {
-
- private Config config;
-
- private ServerInfo serverInfo;
-
- private Stage stage;
-
- private HostServices hostServices;
-
- public Logger getLogger(){
- return logger;
- }
-
- private SettingsBase settingsBase;
- private DashboardBase dashboardBase;
-
- private StackPane alertStackPane;
-
- public void setHostServices(HostServices hostServices)
- {
- this.hostServices = hostServices;
- }
-
- public HostServices getHostServices()
- {
- return hostServices;
- }
-
- private Logger logger = null;
- private StreamPiLogFileHandler logFileHandler = null;
-
- public void initLogger() throws SevereException
- {
- try
- {
- if(logger != null)
- return;
-
- logger = Logger.getLogger("");
- logFileHandler = new StreamPiLogFileHandler(ServerInfo.getInstance().getPrePath()+"../streampi.log");
- logger.addHandler(logFileHandler);
- }
- catch(Exception e)
- {
- e.printStackTrace();
- throw new SevereException("Cant get logger started!");
- }
- }
-
- public void closeLogger()
- {
- if(logFileHandler != null)
- logFileHandler.close();
- }
-
- public void initBase() throws SevereException {
- initLogger();
-
- getChildren().clear();
-
- stage = (Stage) getScene().getWindow();
-
- getStage().getIcons().add(new Image(Main.class.getResourceAsStream("app_icon.png")));
-
- getStage().setMinWidth(500);
- getStage().setMinHeight(500);
-
- config = Config.getInstance();
-
- stage.setWidth(config.getStartupWindowWidth());
- stage.setHeight(config.getStartupWindowHeight());
- stage.centerOnScreen();
-
-
- serverInfo = ServerInfo.getInstance();
-
-
- initThemes();
-
- settingsBase = new SettingsBase(getHostServices(), this, this);
- settingsBase.prefWidthProperty().bind(widthProperty());
- settingsBase.prefHeightProperty().bind(heightProperty());
-
- dashboardBase = new DashboardBase(this, getHostServices());
- dashboardBase.prefWidthProperty().bind(widthProperty());
- dashboardBase.prefHeightProperty().bind(heightProperty());
-
- alertStackPane = new StackPane();
- alertStackPane.setVisible(false);
-
- StreamPiAlert.setParent(alertStackPane);
-
- getChildren().addAll(settingsBase, dashboardBase, alertStackPane);
-
- dashboardBase.toFront();
-
-
- }
-
- public void initThemes() throws SevereException {
- clearStylesheets();
-
- registerThemes();
- applyDefaultStylesheet();
- applyDefaultTheme();
- }
-
- public Stage getStage()
- {
- return stage;
- }
-
- public void applyDefaultStylesheet()
- {
- logger.info("Applying default stylesheet ...");
-
- Font.loadFont(Main.class.getResourceAsStream("Roboto.ttf"), 13);
- getStylesheets().add(Main.class.getResource("style.css").toExternalForm());
-
- logger.info("... Done!");
- }
-
- public DashboardBase getDashboardPane()
- {
- return dashboardBase;
- }
-
- public SettingsBase getSettingsPane()
- {
- return settingsBase;
- }
-
-
- public Config getConfig()
- {
- return config;
- }
-
- public ServerInfo getServerInfo()
- {
- return serverInfo;
- }
-
- private Theme currentTheme;
- public Theme getCurrentTheme()
- {
- return currentTheme;
- }
-
- public void applyTheme(Theme t)
- {
- logger.info("Applying theme '"+t.getFullName()+"' ...");
-
- if(t.getFonts() != null)
- {
- for(String fontFile : t.getFonts())
- {
- Font.loadFont(fontFile.replace("%20",""), 13);
- }
- }
-
- currentTheme = t;
- getStylesheets().addAll(t.getStylesheets());
-
- logger.info("... Done!");
- }
-
- public void clearStylesheets()
- {
- getStylesheets().clear();
- }
-
- Themes themes;
- public void registerThemes() throws SevereException
- {
- logger.info("Loading themes ...");
- themes = new Themes(getConfig().getThemesPath(), getConfig().getCurrentThemeFullName(), serverInfo.getMinThemeSupportVersion());
-
- if(themes.getErrors().size()>0)
- {
- StringBuilder themeErrors = new StringBuilder();
-
- for(MinorException eachException : themes.getErrors())
- {
- themeErrors.append("\n * ").append(eachException.getShortMessage());
- }
-
- if(themes.getIsBadThemeTheCurrentOne())
- {
- themeErrors.append("\n\nReverted to default theme! (").append(getConfig().getDefaultCurrentThemeFullName()).append(")");
-
- getConfig().setCurrentThemeFullName(getConfig().getDefaultCurrentThemeFullName());
- getConfig().save();
- }
-
- handleMinorException(new MinorException("Theme Loading issues", themeErrors.toString()));
- }
-
-
- logger.info("... Done!");
- }
-
- public Themes getThemes()
- {
- return themes;
- }
-
- public void applyDefaultTheme()
- {
- logger.info("Applying default theme ...");
-
-
-
- boolean foundTheme = false;
- for(Theme t: themes.getThemeList())
- {
- if(t.getFullName().equals(config.getCurrentThemeFullName()))
- {
- foundTheme = true;
- applyTheme(t);
- break;
- }
- }
-
- if(foundTheme)
- logger.info("... Done!");
- else
- {
- logger.info("Theme not found. reverting to light theme ...");
- try {
- Config.getInstance().setCurrentThemeFullName("com.StreamPi.DefaultLight");
- Config.getInstance().save();
-
- applyDefaultTheme();
- }
- catch (SevereException e)
- {
- handleSevereException(e);
- }
- }
-
-
- }
-
-
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/Dashboard/ActionGridPane/ActionBox.java'
+++ /dev/null
@@ -1,367 +0,0 @@
-package com.StreamPi.Server.Window.Dashboard.ActionGridPane;
-
-import com.StreamPi.ActionAPI.Action.Action;
-import com.StreamPi.ActionAPI.Action.ActionType;
-import com.StreamPi.ActionAPI.Action.DisplayTextAlignment;
-import com.StreamPi.ActionAPI.Action.Location;
-import com.StreamPi.ActionAPI.OtherActions.CombineAction;
-import com.StreamPi.ActionAPI.OtherActions.FolderAction;
-import com.StreamPi.Server.Window.ExceptionAndAlertHandler;
-import com.StreamPi.Server.Window.Dashboard.ActionsDetailPane.ActionDetailsPaneListener;
-import com.StreamPi.Util.Exception.MinorException;
-import javafx.application.Platform;
-import javafx.css.CssMetaData;
-import javafx.css.Styleable;
-import javafx.geometry.Insets;
-import javafx.geometry.Pos;
-import javafx.scene.CacheHint;
-import javafx.scene.SnapshotParameters;
-import javafx.scene.control.ContextMenu;
-import javafx.scene.control.Label;
-import javafx.scene.control.MenuItem;
-import javafx.scene.image.Image;
-import javafx.scene.image.ImageView;
-import javafx.scene.image.WritableImage;
-import javafx.scene.input.ClipboardContent;
-import javafx.scene.input.Dragboard;
-import javafx.scene.input.MouseButton;
-import javafx.scene.input.TransferMode;
-import javafx.scene.layout.Background;
-import javafx.scene.layout.BackgroundFill;
-import javafx.scene.layout.BackgroundImage;
-import javafx.scene.layout.BackgroundPosition;
-import javafx.scene.layout.BackgroundRepeat;
-import javafx.scene.layout.BackgroundSize;
-import javafx.scene.layout.CornerRadii;
-import javafx.scene.layout.StackPane;
-import javafx.scene.paint.Color;
-import javafx.scene.paint.ImagePattern;
-import javafx.scene.paint.Paint;
-import javafx.scene.shape.Rectangle;
-import javafx.scene.text.TextAlignment;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.nio.ByteBuffer;
-import java.util.function.Consumer;
-
-public class ActionBox extends StackPane{
-
- private Label displayTextLabel;
-
- private int row;
- private int col;
-
- public void setRow(int row) {
- this.row = row;
- }
-
- public void setCol(int col) {
- this.col = col;
- }
-
- public int getRow() {
- return row;
- }
-
- public int getCol() {
- return col;
- }
-
- private ActionDetailsPaneListener actionDetailsPaneListener;
-
- public void clear()
- {
- setAction(null);
- setInvalid(false);
- setBackground(Background.EMPTY);
- setStyle(null);
- getChildren().clear();
- }
-
- public void baseInit()
- {
-
- displayTextLabel = new Label();
- displayTextLabel.setWrapText(true);
- displayTextLabel.setTextAlignment(TextAlignment.CENTER);
- displayTextLabel.getStyleClass().add("action_box_display_text_label");
-
- displayTextLabel.prefHeightProperty().bind(heightProperty());
- displayTextLabel.prefWidthProperty().bind(widthProperty());
-
-
- getChildren().addAll(displayTextLabel);
-
- setMinSize(size, size);
- setMaxSize(size, size);
-
- getStyleClass().add("action_box");
- getStyleClass().add("action_box_icon_not_present");
- getStyleClass().add("action_box_valid");
-
-
- setOnDragOver(dragEvent ->
- {
- if(dragEvent.getDragboard().hasContent(Action.getDataFormat()))
- {
- dragEvent.acceptTransferModes(TransferMode.ANY);
-
- dragEvent.consume();
- }
- });
-
- setOnDragDropped(dragEvent ->
- {
- try
- {
- if(action == null)
- {
- Action action = (Action) dragEvent.getDragboard().getContent(Action.getDataFormat());
-
- action.setLocation(new Location(getRow(),
- getCol()));
-
- action.setParent(getStreamPiParent());
-
- action.setIDRandom();
-
-
- actionGridPaneListener.addActionToCurrentClientProfile(action);
-
- setAction(action);
- init();
-
-
- actionDetailsPaneListener.onActionClicked(action, this);
-
- if(action.isHasIcon())
- actionDetailsPaneListener.setSendIcon(true);
-
- actionDetailsPaneListener.saveAction();
- }
- }
- catch (MinorException e)
- {
- exceptionAndAlertHandler.handleMinorException(e);
- e.printStackTrace();
- }
- });
-
- setOnDragDetected(mouseEvent -> {
- try {
- if(action!=null)
- {
- if(action.getActionType() == ActionType.NORMAL)
- {
- Dragboard db = startDragAndDrop(TransferMode.ANY);
-
- ClipboardContent content = new ClipboardContent();
-
- Action newAction = (Action) action.clone();
-
- newAction.setIDRandom();
- newAction.setParent(getStreamPiParent());
-
- content.put(Action.getDataFormat(), newAction);
-
- db.setContent(content);
-
- mouseEvent.consume();
- }
- }
- }
- catch (CloneNotSupportedException e)
- {
- e.printStackTrace();
- }
- });
-
- setOnMouseClicked(mouseEvent -> {
- if(action != null && mouseEvent.getButton().equals(MouseButton.PRIMARY))
- {
- if(mouseEvent.getClickCount() == 2 && action.getActionType() == ActionType.FOLDER)
- {
- getActionDetailsPaneListener().onOpenFolderButtonClicked();
- }
- else
- {
- try
- {
- actionDetailsPaneListener.onActionClicked(action, this);
- }
- catch (MinorException e)
- {
- exceptionAndAlertHandler.handleMinorException(e);
- e.printStackTrace();
- }
- }
- }
- });
-
- setCache(true);
- setCacheHint(CacheHint.SPEED);
- }
-
- public void setInvalid(boolean invalid)
- {
- if(invalid)
- {
- getStyleClass().remove("action_box_valid");
- getStyleClass().add("action_box_invalid");
- }
- else
- {
- getStyleClass().remove("action_box_invalid");
- getStyleClass().add("action_box_valid");
- }
-
- }
-
- public ActionDetailsPaneListener getActionDetailsPaneListener() {
- return actionDetailsPaneListener;
- }
-
-
- public ActionGridPaneListener getActionGridPaneListener() {
- return actionGridPaneListener;
- }
-
- private int size;
- private ActionGridPaneListener actionGridPaneListener;
- public ActionBox(int size, ActionDetailsPaneListener actionDetailsPaneListener, ActionGridPaneListener actionGridPaneListener)
- {
- this.actionGridPaneListener = actionGridPaneListener;
- this.actionDetailsPaneListener = actionDetailsPaneListener;
- this.size = size;
- baseInit();
- }
-
- public static Action deserialize(ByteBuffer buffer) {
- try {
- ByteArrayInputStream is = new ByteArrayInputStream(buffer.array());
- ObjectInputStream ois = new ObjectInputStream(is);
- Action obj = (Action) ois.readObject();
- return obj;
- } catch (Exception e) {
- e.printStackTrace();
- throw new RuntimeException(e);
- }
- }
-
- public void setIcon(byte[] iconByteArray)
- {
- if(iconByteArray == null)
- {
- getStyleClass().remove("action_box_icon_present");
- getStyleClass().add("action_box_icon_not_present");
- setBackground(null);
- return;
- }
- else
- {
- getStyleClass().add("action_box_icon_present");
- getStyleClass().remove("action_box_icon_not_present");
-
-
- setBackground(
- new Background(
- new BackgroundImage(new Image(
- new ByteArrayInputStream(iconByteArray), size, size, false, true
- ), BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.CENTER,
-
- new BackgroundSize(100, 100, true, true, true, false))
- )
- );
- }
- }
-
- private Action action;
- private ExceptionAndAlertHandler exceptionAndAlertHandler;
-
- private String parent;
-
- public String getStreamPiParent() {
- return parent;
- }
-
- public void setStreamPiParent(String parent) {
- this.parent = parent;
- }
-
- public ActionBox(int size, Action action, ActionDetailsPaneListener actionDetailsPaneListener, ExceptionAndAlertHandler exceptionAndAlertHandler, ActionGridPaneListener actionGridPaneListener)
- {
- this.actionGridPaneListener = actionGridPaneListener;
- this.exceptionAndAlertHandler = exceptionAndAlertHandler;
- this.action = action;
- this.actionDetailsPaneListener = actionDetailsPaneListener;
- this.size = size;
-
-
-
- baseInit();
-
- init();
-
- }
-
- public void setAction(Action action)
- {
- this.action = action;
- }
-
- public void init()
- {
- if(action.isShowDisplayText())
- setDisplayTextLabel(action.getDisplayText());
- else
- setDisplayTextLabel("");
-
- setDisplayTextAlignment(action.getDisplayTextAlignment());
- setBackgroundColour(action.getBgColourHex());
- setDisplayTextFontColour(action.getDisplayTextFontColourHex());
-
- setInvalid(action.isInvalid());
-
- Platform.runLater(()->{
- if(action.isHasIcon() && action.isShowIcon())
- {
- setIcon(action.getIconAsByteArray());
- }
- else
- {
- setIcon(null);
- }
- });
- }
-
- public void setDisplayTextLabel(String text)
- {
- displayTextLabel.setText(text);
- }
-
- public void setDisplayTextAlignment(DisplayTextAlignment displayTextAlignment)
- {
- if(displayTextAlignment == DisplayTextAlignment.CENTER)
- displayTextLabel.setAlignment(Pos.CENTER);
- else if (displayTextAlignment == DisplayTextAlignment.BOTTOM)
- displayTextLabel.setAlignment(Pos.BOTTOM_CENTER);
- else if (displayTextAlignment == DisplayTextAlignment.TOP)
- displayTextLabel.setAlignment(Pos.TOP_CENTER);
- }
-
- public void setDisplayTextFontColour(String colour)
- {
- System.out.println("COLOr : "+colour);
- if(!colour.isEmpty())
- displayTextLabel.setStyle("-fx-text-fill : "+colour+";");
- }
-
- public void setBackgroundColour(String colour)
- {
- System.out.println("COLOr : "+colour);
- if(!colour.isEmpty() && action.getIconAsByteArray() == null)
- setStyle("-fx-background-color : "+colour);
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/Dashboard/ActionGridPane/ActionGridPane.java'
+++ /dev/null
@@ -1,303 +0,0 @@
-package com.StreamPi.Server.Window.Dashboard.ActionGridPane;
-
-import com.StreamPi.ActionAPI.Action.Action;
-import com.StreamPi.ActionAPI.Action.Location;
-import com.StreamPi.ActionAPI.ActionProperty.Property.Property;
-import com.StreamPi.ActionAPI.OtherActions.FolderAction;
-import com.StreamPi.Server.Client.Client;
-import com.StreamPi.Server.Client.ClientProfile;
-import com.StreamPi.Server.Connection.ServerListener;
-import com.StreamPi.Server.IO.Config;
-import com.StreamPi.Server.Window.ExceptionAndAlertHandler;
-import com.StreamPi.Server.Window.Dashboard.ActionsDetailPane.ActionDetailsPaneListener;
-import com.StreamPi.ThemeAPI.Themes;
-import com.StreamPi.Util.Exception.MinorException;
-import com.StreamPi.Util.Exception.SevereException;
-import javafx.event.EventHandler;
-import javafx.geometry.Insets;
-import javafx.geometry.Pos;
-import javafx.scene.CacheHint;
-import javafx.scene.Node;
-import javafx.scene.control.ScrollPane;
-import javafx.scene.input.MouseEvent;
-import javafx.scene.layout.*;
-import javafx.scene.paint.Paint;
-import org.kordamp.ikonli.javafx.FontIcon;
-
-import java.util.ArrayList;
-import java.util.logging.Logger;
-
-public class ActionGridPane extends ScrollPane implements ActionGridPaneListener {
-
- private ExceptionAndAlertHandler exceptionAndAlertHandler;
- private ActionDetailsPaneListener actionDetailsPaneListener;
-
- public ActionGridPane(ExceptionAndAlertHandler exceptionAndAlertHandler)
- {
- logger = Logger.getLogger(ActionGridPane.class.getName());
- this.exceptionAndAlertHandler = exceptionAndAlertHandler;
- getStyleClass().add("action_grid_pane_scroll_pane");
-
- VBox.setVgrow(this, Priority.ALWAYS);
-
- actionsGridPane = new GridPane();
- actionsGridPane.setPadding(new Insets(5.0));
- actionsGridPane.getStyleClass().add("action_grid_pane");
-
- actionsGridPane.setPrefSize(USE_COMPUTED_SIZE, USE_COMPUTED_SIZE);
-
- setContent(actionsGridPane);
- }
-
- public void setActionDetailsPaneListener(ActionDetailsPaneListener actionDetailsPaneListener) {
- this.actionDetailsPaneListener = actionDetailsPaneListener;
- }
-
- private String currentParent;
-
- public void setCurrentParent(String currentParent) {
- this.currentParent = currentParent;
- }
-
- public ClientProfile getClientProfile() {
- return clientProfile;
- }
-
- private Client client;
-
- public void setClient(Client client) {
- this.client = client;
- }
-
- public Client getClient() {
- return client;
- }
-
- private int rows, cols;
-
- private GridPane actionsGridPane;
-
- private ClientProfile clientProfile;
-
- public void setClientProfile(ClientProfile clientProfile)
- {
- this.clientProfile = clientProfile;
-
- setCurrentParent("root");
- setRows(clientProfile.getRows());
- setCols(clientProfile.getCols());
- }
-
-
- public String getCurrentParent() {
- return currentParent;
- }
-
- public StackPane getFolderBackButton() throws SevereException
- {
- StackPane stackPane = new StackPane();
- stackPane.getStyleClass().add("action_box");
- stackPane.getStyleClass().add("action_box_valid");
-
- stackPane.setPrefSize(
- Config.getInstance().getActionGridActionSize(),
- Config.getInstance().getActionGridActionSize()
- );
-
- FontIcon fontIcon = new FontIcon("fas-chevron-left");
-
- fontIcon.setIconSize(Config.getInstance().getActionGridActionSize() - 30);
-
- stackPane.setAlignment(Pos.CENTER);
- stackPane.getChildren().add(fontIcon);
-
- stackPane.setOnMouseClicked(e->returnToPreviousParent());
-
- return stackPane;
- }
-
- public void renderGrid() throws SevereException {
- clear();
-
- actionsGridPane.setHgap(Config.getInstance().getActionGridActionGap());
- actionsGridPane.setVgap(Config.getInstance().getActionGridActionGap());
-
- boolean isFolder = false;
-
- if(!getCurrentParent().equals("root"))
- {
- isFolder = true;
-
- actionsGridPane.add(getFolderBackButton(), 0,0);
- }
-
- for(int row = 0; row<rows; row++)
- {
- for(int col = 0; col<cols; col++)
- {
- if(row == 0 && col == 0 && isFolder)
- continue;
-
- ActionBox actionBox = new ActionBox(Config.getInstance().getActionGridActionSize(), actionDetailsPaneListener, this);
-
- actionBox.setStreamPiParent(currentParent);
- actionBox.setRow(row);
- actionBox.setCol(col);
-
- actionsGridPane.add(actionBox, row, col);
-
- }
- }
- }
-
- public void renderActions()
- {
- StringBuilder errors = new StringBuilder();
- for(String action1x : getClientProfile().getActionsKeySet())
- {
- Action eachAction = getClientProfile().getActionByID(action1x);
- logger.info("Action ID : "+eachAction.getID()+
- "\nInvalid : "+eachAction.isInvalid());
-
- try {
- renderAction(eachAction);
- }
- catch (SevereException e)
- {
- exceptionAndAlertHandler.handleSevereException(e);
- }
- catch (MinorException e)
- {
- errors.append("*").append(e.getShortMessage()).append("\n");
- }
- }
-
- if(!errors.toString().isEmpty())
- {
- exceptionAndAlertHandler.handleMinorException(new MinorException("Error while rendering following actions", errors.toString()));
- }
- }
-
- public void clear()
- {
- actionsGridPane.getChildren().clear();
- }
-
- private Logger logger;
-
- public void renderAction(Action action) throws SevereException, MinorException
- {
- if(!action.getParent().equals(currentParent))
- {
- logger.info("Skipping action "+action.getID()+", not current parent!");
- return;
- }
-
- if(action.getLocation().getRow()==-1)
- {
- logger.info("Action has -1 rowIndex. Probably Combine Action. Skipping ...");
- return;
- }
-
- if(action.getLocation().getRow() >= rows || action.getLocation().getCol() >= cols)
- {
- throw new MinorException("Action "+action.getDisplayText()+" ("+action.getID()+") falls outside bounds.\n" +
- " Consider increasing rows/cols from client settings and relocating/deleting it.");
- }
-
-
- ActionBox actionBox = new ActionBox(Config.getInstance().getActionGridActionSize(), action, actionDetailsPaneListener, exceptionAndAlertHandler, this);
-
- Location location = action.getLocation();
-
- actionBox.setStreamPiParent(currentParent);
- actionBox.setRow(location.getRow());
- actionBox.setCol(location.getCol());
-
- for(Node node : actionsGridPane.getChildren())
- {
- if(GridPane.getColumnIndex(node) == location.getRow() &&
- GridPane.getRowIndex(node) == location.getCol())
- {
- actionsGridPane.getChildren().remove(node);
- break;
- }
- }
-
- System.out.println(location.getCol()+","+location.getRow());
- actionsGridPane.add(actionBox, location.getRow(), location.getCol());
-
- }
-
- public void setRows(int rows)
- {
- this.rows = rows;
- }
-
- public void setCols(int cols)
- {
- this.cols = cols;
- }
-
- public int getRows()
- {
- return rows;
- }
-
- public int getCols()
- {
- return cols;
- }
-
-
- @Override
- public void addActionToCurrentClientProfile(Action newAction) {
- try {
- getClientProfile().addAction(newAction);
- } catch (CloneNotSupportedException e) {
- e.printStackTrace();
- }
- }
-
- private String previousParent;
-
- public void setPreviousParent(String previousParent) {
- this.previousParent = previousParent;
- }
-
- public String getPreviousParent() {
- return previousParent;
- }
-
- @Override
- public void renderFolder(FolderAction action) {
- setCurrentParent(action.getID());
- setPreviousParent(action.getParent());
- try {
- renderGrid();
- renderActions();
- } catch (SevereException e) {
- e.printStackTrace();
- }
- }
-
- public void returnToPreviousParent()
- {
- setCurrentParent(getPreviousParent());
-
- if(!getPreviousParent().equals("root"))
- {
- System.out.println("parent : "+getPreviousParent());
- setPreviousParent(getClientProfile().getActionByID(
- getPreviousParent()
- ).getParent());
- }
-
- try {
- renderGrid();
- renderActions();
- } catch (SevereException e) {
- e.printStackTrace();
- }
- }
-}
D
src/main/java/com/StreamPi/Server/Window/Dashboard/ActionGridPane/ActionGridPaneListener.java
+0
−10
--- 'a/src/main/java/com/StreamPi/Server/Window/Dashboard/ActionGridPane/ActionGridPaneListener.java'
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.StreamPi.Server.Window.Dashboard.ActionGridPane;
-
-import com.StreamPi.ActionAPI.Action.Action;
-import com.StreamPi.ActionAPI.OtherActions.FolderAction;
-
-public interface ActionGridPaneListener {
- void addActionToCurrentClientProfile(Action newAction);
-
- void renderFolder(FolderAction action);
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/Dashboard/ActionsDetailPane/ActionDetailsPane.java'
+++ /dev/null
@@ -1,810 +0,0 @@
-package com.StreamPi.Server.Window.Dashboard.ActionsDetailPane;
-
-import com.StreamPi.Server.UIPropertyBox.UIPropertyBox;
-import com.StreamPi.ActionAPI.Action.Action;
-import com.StreamPi.ActionAPI.Action.ActionType;
-import com.StreamPi.ActionAPI.Action.DisplayTextAlignment;
-import com.StreamPi.ActionAPI.Action.Location;
-import com.StreamPi.ActionAPI.ActionProperty.ClientProperties;
-import com.StreamPi.ActionAPI.ActionProperty.Property.ControlType;
-import com.StreamPi.ActionAPI.ActionProperty.Property.Property;
-import com.StreamPi.ActionAPI.ActionProperty.Property.Type;
-import com.StreamPi.ActionAPI.OtherActions.CombineAction;
-import com.StreamPi.ActionAPI.OtherActions.FolderAction;
-import com.StreamPi.Server.Client.Client;
-import com.StreamPi.Server.Client.ClientProfile;
-import com.StreamPi.Server.Connection.ClientConnection;
-import com.StreamPi.Server.Connection.ClientConnections;
-import com.StreamPi.Server.Window.Dashboard.ActionGridPane.ActionBox;
-import com.StreamPi.Server.Window.ExceptionAndAlertHandler;
-import com.StreamPi.Util.Exception.MinorException;
-import com.StreamPi.Util.Exception.SevereException;
-import com.StreamPi.Util.FormHelper.HBoxInputBox;
-import com.StreamPi.Util.FormHelper.HBoxInputBoxWithFileChooser;
-import com.StreamPi.Util.FormHelper.SpaceFiller;
-import javafx.application.HostServices;
-import javafx.application.Platform;
-import javafx.collections.FXCollections;
-import javafx.concurrent.Task;
-import javafx.geometry.Insets;
-import javafx.geometry.Pos;
-import javafx.scene.Node;
-import javafx.scene.control.*;
-import javafx.scene.input.TransferMode;
-import javafx.scene.layout.HBox;
-import javafx.scene.layout.Priority;
-import javafx.scene.layout.Region;
-import javafx.scene.layout.VBox;
-import javafx.scene.paint.Color;
-import javafx.scene.paint.Paint;
-import javafx.stage.FileChooser;
-import javafx.stage.Window;
-import org.kordamp.ikonli.javafx.FontIcon;
-
-import java.io.File;
-import java.nio.file.Files;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.logging.Logger;
-
-public class ActionDetailsPane extends VBox implements ActionDetailsPaneListener {
-
- private ScrollPane scrollPane;
-
- private VBox vbox;
- private VBox clientPropertiesVBox;
-
- private Button saveButton;
- private Button deleteButton;
- private Button openFolderButton;
-
- private HBox buttonBar;
-
- private Label actionHeadingLabel;
-
- private Logger logger;
-
- private Button returnButtonForCombineActionChild;
-
- private ExceptionAndAlertHandler exceptionAndAlertHandler;
-
- private HostServices hostServices;
-
- public ActionDetailsPane(ExceptionAndAlertHandler exceptionAndAlertHandler, HostServices hostServices) {
- this.hostServices = hostServices;
- this.exceptionAndAlertHandler = exceptionAndAlertHandler;
-
- logger = Logger.getLogger(ActionDetailsPane.class.getName());
-
- setSpacing(10.0);
-
- // VBox.setVgrow(this, Priority.SOMETIMES);
-
- clientPropertiesVBox = new VBox();
- clientPropertiesVBox.setSpacing(10.0);
-
- vbox = new VBox();
- vbox.setPadding(new Insets(0, 25, 0, 5));
- vbox.getStyleClass().add("action_details_pane_vbox");
-
- vbox.setSpacing(10.0);
-
- getStyleClass().add("action_details_pane");
- // setPadding(new Insets(5,50,5,50));
- // setMinHeight(245);
-
- scrollPane = new ScrollPane();
- VBox.setMargin(scrollPane, new Insets(0, 0, 0, 10));
-
- scrollPane.getStyleClass().add("action_details_pane_scroll_pane");
-
- setMinHeight(310);
- scrollPane.setContent(vbox);
-
- vbox.prefWidthProperty().bind(scrollPane.widthProperty());
- scrollPane.prefWidthProperty().bind(widthProperty());
-
- VBox.setVgrow(scrollPane, Priority.ALWAYS);
-
- scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
-
- openFolderButton = new Button("Open Folder");
- FontIcon folderOpenIcon = new FontIcon("far-folder-open");
- openFolderButton.setGraphic(folderOpenIcon);
- openFolderButton.setOnAction(event -> onOpenFolderButtonClicked());
-
- saveButton = new Button("Apply Changes");
- FontIcon syncIcon = new FontIcon("fas-sync-alt");
- saveButton.setGraphic(syncIcon);
- saveButton.setOnAction(event -> onSaveButtonClicked());
-
- deleteButton = new Button("Delete Action");
- FontIcon deleteIcon = new FontIcon("fas-trash");
- deleteIcon.setIconColor(Paint.valueOf("#FF0000"));
- deleteButton.setTextFill(Paint.valueOf("#FF0000"));
- deleteButton.setGraphic(deleteIcon);
-
- deleteButton.setOnAction(event -> onDeleteButtonClicked());
-
- returnButtonForCombineActionChild = new Button("Return");
- returnButtonForCombineActionChild.setGraphic(new FontIcon("fas-caret-left"));
- returnButtonForCombineActionChild.managedProperty().bind(returnButtonForCombineActionChild.visibleProperty());
- returnButtonForCombineActionChild.setOnAction(event -> {
- try {
- logger.info("@@## : " + action.getParent());
- onActionClicked(getClientProfile().getActionByID(action.getParent()), getActionBox());
- } catch (MinorException e) {
- e.printStackTrace();
- }
- });
-
- buttonBar = new HBox(openFolderButton, returnButtonForCombineActionChild, saveButton, deleteButton);
- buttonBar.setPadding(new Insets(10, 10, 10, 0));
- buttonBar.setAlignment(Pos.CENTER_RIGHT);
- buttonBar.setVisible(false);
- buttonBar.setSpacing(10.0);
-
- actionHeadingLabel = new Label();
-
- actionHeadingLabel.getStyleClass().add("action_details_pane_action_heading_label");
-
- HBox headingHBox = new HBox(actionHeadingLabel);
-
- headingHBox.setPadding(new Insets(5, 10, 0, 10));
-
- getChildren().addAll(headingHBox, scrollPane, buttonBar);
-
- displayTextAlignmentComboBox = new ComboBox<>(FXCollections.observableArrayList(DisplayTextAlignment.TOP,
- DisplayTextAlignment.CENTER, DisplayTextAlignment.BOTTOM));
-
- displayTextAlignmentComboBox.managedProperty().bind(displayTextAlignmentComboBox.visibleProperty());
-
- actionClientProperties = new ArrayList<>();
-
- displayNameTextField = new TextField();
- displayNameTextField.managedProperty().bind(displayNameTextField.visibleProperty());
-
- iconFileTextField = new TextField();
- iconFileTextField.managedProperty().bind(iconFileTextField.visibleProperty());
- iconFileTextField.textProperty().addListener((observableValue, s, t1) -> {
- try {
- if (!s.equals(t1) && t1.length() > 0) {
- byte[] iconFileByteArray = Files.readAllBytes(new File(t1).toPath());
-
- hideIconCheckBox.setDisable(false);
- hideIconCheckBox.setSelected(false);
- clearIconButton.setDisable(false);
-
- System.out.println("ABABABABABBABABBABABABCCCCCCCCCCCCCCCCCC");
-
- action.setIcon(iconFileByteArray);
- setSendIcon(true);
-
- System.out.println(action.getIconAsByteArray().length);
- }
- } catch (Exception e) {
- e.printStackTrace();
- exceptionAndAlertHandler.handleMinorException(new MinorException(e.getMessage()));
- }
- });
-
- clearIconButton = new Button("Clear Icon");
- clearIconButton.managedProperty().bind(clearIconButton.visibleProperty());
- clearIconButton.setOnAction(event -> {
-
- hideIconCheckBox.setDisable(true);
- hideIconCheckBox.setSelected(false);
-
- clearIconButton.setDisable(true);
- iconFileTextField.clear();
- });
-
- hideDisplayTextCheckBox = new CheckBox("Hide");
- hideDisplayTextCheckBox.managedProperty().bind(hideDisplayTextCheckBox.visibleProperty());
-
- hideIconCheckBox = new CheckBox("Hide");
- hideIconCheckBox.managedProperty().bind(hideIconCheckBox.visibleProperty());
-
- actionBackgroundColourPicker = new ColorPicker();
- actionBackgroundColourPicker.managedProperty().bind(actionBackgroundColourPicker.visibleProperty());
-
- displayTextColourPicker = new ColorPicker();
- displayTextColourPicker.managedProperty().bind(displayTextColourPicker.visibleProperty());
-
- actionBackgroundColourTransparentCheckBox = new CheckBox("Default");
- actionBackgroundColourPicker.disableProperty()
- .bind(actionBackgroundColourTransparentCheckBox.selectedProperty());
-
- HBox.setMargin(actionBackgroundColourTransparentCheckBox, new Insets(0, 0, 0, 10));
-
-
- displayTextColourDefaultCheckBox = new CheckBox("Default");
- displayTextColourPicker.disableProperty()
- .bind(displayTextColourDefaultCheckBox.selectedProperty());
-
- HBox.setMargin(displayTextColourDefaultCheckBox, new Insets(0, 0, 0, 10));
-
- Region r = new Region();
- HBox.setHgrow(r, Priority.ALWAYS);
-
- Region r1 = new Region();
- HBox.setHgrow(r1, Priority.ALWAYS);
-
- HBox displayTextColourHBox = new HBox(new Label("Display Text Colour"), r1, displayTextColourPicker,
- displayTextColourDefaultCheckBox);
- displayTextColourHBox.setAlignment(Pos.CENTER);
- displayTextColourHBox.setSpacing(5.0);
-
- HBox bgColourHBox = new HBox(new Label("Background Colour"), r, actionBackgroundColourPicker,
- actionBackgroundColourTransparentCheckBox);
- bgColourHBox.setAlignment(Pos.CENTER);
- bgColourHBox.setSpacing(5.0);
-
- HBox clearIconHBox = new HBox(clearIconButton);
- clearIconHBox.setAlignment(Pos.CENTER_RIGHT);
-
- displayTextFieldHBox = new HBoxInputBox("Display Name", displayNameTextField, hideDisplayTextCheckBox);
-
- normalActionsPropsVBox = new VBox(displayTextColourHBox,
-
- new HBox(new Label("Alignment"), new SpaceFiller(SpaceFiller.FillerType.HBox),
- displayTextAlignmentComboBox),
-
- new HBoxInputBoxWithFileChooser("Icon", iconFileTextField, hideIconCheckBox,
- new FileChooser.ExtensionFilter("Images", "*.jpeg", "*.jpg", "*.png", "*.gif")),
-
- clearIconHBox, bgColourHBox);
- normalActionsPropsVBox.managedProperty().bind(normalActionsPropsVBox.visibleProperty());
- normalActionsPropsVBox.setSpacing(10.0);
-
- vbox.getChildren().addAll(displayTextFieldHBox, normalActionsPropsVBox, clientPropertiesVBox);
-
- vbox.setVisible(false);
- scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
-
- setOnDragOver(dragEvent -> {
- if (dragEvent.getDragboard().hasContent(Action.getDataFormat()) && action != null) {
- if (action.getActionType() == ActionType.COMBINE) {
- dragEvent.acceptTransferModes(TransferMode.ANY);
-
- dragEvent.consume();
- }
- }
- });
-
- setOnDragDropped(dragEvent -> {
- try {
- Action newAction = (Action) dragEvent.getDragboard().getContent(Action.getDataFormat());
-
- if (newAction.getActionType() == ActionType.NORMAL) {
- newAction.setLocation(new Location(-1, -1));
-
- newAction.setParent(this.action.getID());
-
- combineActionPropertiesPane.getCombineAction().addChild(newAction.getID());
-
- addActionToCurrentClientProfile(newAction);
-
- ClientConnection connection = ClientConnections.getInstance()
- .getClientConnectionBySocketAddress(getClient().getRemoteSocketAddress());
-
- connection.saveActionDetails(getClientProfile().getID(), newAction);
-
- combineActionPropertiesPane.renderProps();
-
- saveAction();
- }
- } catch (MinorException e) {
- exceptionAndAlertHandler.handleMinorException(e);
- e.printStackTrace();
- } catch (SevereException e) {
- exceptionAndAlertHandler.handleSevereException(e);
- e.printStackTrace();
- } catch (CloneNotSupportedException e) {
- e.printStackTrace();
- }
- });
- }
-
- private VBox normalActionsPropsVBox;
-
- private HBox displayTextFieldHBox;
-
- private Client client;
- private ClientProfile clientProfile;
-
- public void setClient(Client client) {
- this.client = client;
- }
-
- public Client getClient() {
- return client;
- }
-
- public void setClientProfile(ClientProfile clientProfile) {
- this.clientProfile = clientProfile;
- }
-
- public ClientProfile getClientProfile() {
- return clientProfile;
- }
-
- public void setActionHeadingLabelText(String text) {
- actionHeadingLabel.setText(text);
- }
-
- private Action action;
-
- public Action getAction() {
- return action;
- }
-
- private ActionBox actionBox;
-
- public ActionBox getActionBox() {
- return actionBox;
- }
-
- @Override
- public void onActionClicked(Action action, ActionBox actionBox) throws MinorException {
- this.action = action;
- this.actionBox = actionBox;
-
- System.out.println(action.getActionType());
-
-
- logger.info("Action Display text : "+action.getDisplayText());
- clear();
-
- renderActionProperties();
- }
-
- private TextField displayNameTextField;
- private CheckBox hideDisplayTextCheckBox;
- private CheckBox hideIconCheckBox;
- private TextField iconFileTextField;
- private Button clearIconButton;
- private ColorPicker actionBackgroundColourPicker;
- private ColorPicker displayTextColourPicker;
- private CheckBox actionBackgroundColourTransparentCheckBox;
- private CheckBox displayTextColourDefaultCheckBox;
- private ComboBox<DisplayTextAlignment> displayTextAlignmentComboBox;
-
- public void clear()
- {
- sendIcon = false;
- actionClientProperties.clear();
- displayNameTextField.clear();
- iconFileTextField.clear();
- clientPropertiesVBox.getChildren().clear();
- vbox.setVisible(false);
- scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
- buttonBar.setVisible(false);
- setActionHeadingLabelText("");
-
- actionBackgroundColourPicker.setValue(Color.WHITE);
- displayTextColourPicker.setValue(Color.WHITE);
- }
-
- boolean isCombineChild = false;
-
- public boolean isCombineChild() {
- return isCombineChild;
- }
-
- public void renderActionProperties() throws MinorException
- {
-
- if(action.getLocation().getCol() == -1) //Combine Child action
- isCombineChild = true;
- else
- isCombineChild = false;
-
- displayNameTextField.setText(action.getDisplayText());
-
- System.out.println(action.getDisplayText()+"@@@@::::"+isCombineChild);
-
- if(isCombineChild)
- {
- setReturnButtonForCombineActionChildVisible(true);
- normalActionsPropsVBox.setVisible(false);
- hideDisplayTextCheckBox.setSelected(false);
- hideDisplayTextCheckBox.setVisible(false);
- }
- else
- {
- normalActionsPropsVBox.setVisible(true);
- setReturnButtonForCombineActionChildVisible(false);
- hideDisplayTextCheckBox.setVisible(true);
- setFolderButtonVisible(action.getActionType().equals(ActionType.FOLDER));
-
- displayTextAlignmentComboBox.getSelectionModel().select(action.getDisplayTextAlignment());
-
- if(!action.getBgColourHex().isEmpty())
- actionBackgroundColourPicker.setValue(Color.valueOf(action.getBgColourHex()));
- else
- actionBackgroundColourTransparentCheckBox.setSelected(true);
-
-
-
- if(!action.getDisplayTextFontColourHex().isEmpty())
- displayTextColourPicker.setValue(Color.valueOf(action.getDisplayTextFontColourHex()));
- else
- displayTextColourDefaultCheckBox.setSelected(true);
-
-
- hideDisplayTextCheckBox.setSelected(!action.isShowDisplayText());
-
-
- hideIconCheckBox.setDisable(!action.isHasIcon());
-
- hideIconCheckBox.setSelected(!action.isShowIcon());
-
- if(!action.isHasIcon())
- {
- hideIconCheckBox.setSelected(false);
- }
-
- clearIconButton.setDisable(!action.isHasIcon());
- }
-
-
-
- buttonBar.setVisible(true);
- vbox.setVisible(true);
- scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
-
- if(action.getActionType() == ActionType.NORMAL)
- {
- if(action.isInvalid())
- setActionHeadingLabelText("Invalid Action ("+action.getModuleName()+")");
- else
- setActionHeadingLabelText(action.getName());
- }
- else if(action.getActionType() == ActionType.COMBINE)
- setActionHeadingLabelText("Combine Action");
- else if(action.getActionType() == ActionType.FOLDER)
- setActionHeadingLabelText("Folder Action");
-
-
- if(!action.isInvalid())
- {
- if(action.getActionType() == ActionType.NORMAL)
- renderClientProperties();
- else if(action.getActionType() == ActionType.COMBINE)
- renderCombineActionProperties();
- }
- }
-
- private CombineActionPropertiesPane combineActionPropertiesPane;
-
- public CombineActionPropertiesPane getCombineActionPropertiesPane() {
- return combineActionPropertiesPane;
- }
-
- public void setReturnButtonForCombineActionChildVisible(boolean visible)
- {
- returnButtonForCombineActionChild.setVisible(visible);
- }
-
- public void renderCombineActionProperties()
- {
- try {
- logger.info("@@@@@ : "+action.getClientProperties().getSize());
- combineActionPropertiesPane = new CombineActionPropertiesPane(getActionAsCombineAction(action),
- getClientProfile(),
- this
- );
-
- clientPropertiesVBox.getChildren().add(combineActionPropertiesPane);
- }
- catch (MinorException e)
- {
- e.printStackTrace();
- exceptionAndAlertHandler.handleMinorException(e);
- }
- }
-
- public void setAction(Action action) {
- this.action = action;
- }
-
- public FolderAction getActionAsFolderAction(Action action)
- {
- FolderAction folderAction = new FolderAction();
- folderAction.setDisplayText(action.getDisplayText());
- folderAction.setName(action.getName());
- folderAction.setID(action.getID());
- folderAction.setLocation(action.getLocation());
- folderAction.setBgColourHex(action.getBgColourHex());
- folderAction.setParent(action.getParent());
- folderAction.getClientProperties().set(action.getClientProperties());
- folderAction.setDisplayTextAlignment(action.getDisplayTextAlignment());
- folderAction.setShowIcon(action.isShowIcon());
- folderAction.setHasIcon(action.isHasIcon());
- if(folderAction.isHasIcon())
- folderAction.setIcon(action.getIconAsByteArray());
- folderAction.setDisplayTextFontColourHex(action.getDisplayTextFontColourHex());
-
- return folderAction;
- }
-
- public CombineAction getActionAsCombineAction(Action action)
- {
- CombineAction combineAction = new CombineAction();
- combineAction.setDisplayText(action.getDisplayText());
- combineAction.setName(action.getName());
- combineAction.setID(action.getID());
- combineAction.setLocation(action.getLocation());
- combineAction.setBgColourHex(action.getBgColourHex());
- combineAction.setParent(action.getParent());
- combineAction.getClientProperties().set(action.getClientProperties());
- combineAction.setDisplayTextAlignment(action.getDisplayTextAlignment());
- combineAction.setShowIcon(action.isShowIcon());
- combineAction.setHasIcon(action.isHasIcon());
- if(combineAction.isHasIcon())
- combineAction.setIcon(action.getIconAsByteArray());
- combineAction.setDisplayTextFontColourHex(action.getDisplayTextFontColourHex());
-
- for(Property prop : combineAction.getClientProperties().get())
- {
- System.out.println("PROP : "+prop.getName()+","+prop.getRawValue());
- }
- return combineAction;
- }
-
- public void onOpenFolderButtonClicked()
- {
- FolderAction folderAction = getActionAsFolderAction(action);
- actionBox.getActionGridPaneListener().renderFolder(folderAction);
- clear();
- }
-
- @Override
- public Window getCurrentWindow() {
- return getScene().getWindow();
- }
-
- private ArrayList<UIPropertyBox> actionClientProperties;
-
- public void renderClientProperties() throws MinorException
- {
- for(int i =0;i< action.getClientProperties().getSize(); i++)
- {
- Property eachProperty = action.getClientProperties().get().get(i);
-
- if(!eachProperty.isVisible())
- continue;
-
- Label label = new Label(eachProperty.getDisplayName());
-
- HBox hBox = new HBox(label);
- hBox.setSpacing(5.0);
- hBox.setAlignment(Pos.CENTER_LEFT);
-
- Node controlNode = null;
-
- if(eachProperty.getHelpLink() != null)
- {
- Button helpButton = new Button();
- FontIcon questionIcon = new FontIcon("fas-question");
- helpButton.setGraphic(questionIcon);
-
- helpButton.setOnAction(event -> {
- hostServices.showDocument(eachProperty.getHelpLink());
- });
-
- hBox.getChildren().add(helpButton);
- }
-
- hBox.getChildren().add(new SpaceFiller(SpaceFiller.FillerType.HBox));
-
- if(eachProperty.getControlType() == ControlType.COMBO_BOX)
- {
- ComboBox<String> comboBox = new ComboBox<>();
- comboBox.getItems().addAll(eachProperty.getListValue());
- comboBox.getSelectionModel().select(eachProperty.getSelectedIndex());
-
-
- controlNode = comboBox;
- }
- else if(eachProperty.getControlType() == ControlType.TEXT_FIELD)
- {
- TextField textField = new TextField(eachProperty.getRawValue());
-
- controlNode= textField;
- }
- else if(eachProperty.getControlType() == ControlType.TOGGLE)
- {
- ToggleButton toggleButton = new ToggleButton();
- toggleButton.setSelected(eachProperty.getBoolValue());
-
- if(eachProperty.getBoolValue())
- toggleButton.setText("ON");
- else
- toggleButton.setText("OFF");
-
- toggleButton.selectedProperty().addListener((observableValue, aBoolean, t1) -> {
- if(t1)
- toggleButton.setText("ON");
- else
- toggleButton.setText("OFF");
- });
-
- controlNode = toggleButton;
- }
- else if(eachProperty.getControlType() == ControlType.SLIDER_DOUBLE)
- {
- Slider slider = new Slider();
- slider.setValue(eachProperty.getDoubleValue());
- slider.setMax(eachProperty.getMaxDoubleValue());
- slider.setMin(eachProperty.getMinDoubleValue());
-
- controlNode = slider;
- }
- else if(eachProperty.getControlType() == ControlType.SLIDER_INTEGER)
- {
- Slider slider = new Slider();
- slider.setValue(eachProperty.getIntValue());
-
- slider.setMax(eachProperty.getMaxIntValue());
- slider.setMin(eachProperty.getMinIntValue());
- slider.setBlockIncrement(1.0);
- slider.setSnapToTicks(true);
-
- controlNode = slider;
- }
-
-
- hBox.getChildren().add(controlNode);
-
- UIPropertyBox clientProperty = new UIPropertyBox(i, eachProperty.getDisplayName(), controlNode,
- eachProperty.getControlType(), eachProperty.getType(), eachProperty.isCanBeBlank());
-
- actionClientProperties.add(clientProperty);
-
- clientPropertiesVBox.getChildren().add(hBox);
- }
- }
-
- public void onSaveButtonClicked()
- {
- try {
- // saveButton.setDisable(true);
- // deleteButton.setDisable(true);
-
- validateForm();
-
- saveAction();
- }
- catch (MinorException e)
- {
- exceptionAndAlertHandler.handleMinorException(e);
- }
-
- }
-
- private boolean sendIcon = false;
-
- @Override
- public void setSendIcon(boolean sendIcon)
- {
- this.sendIcon = sendIcon;
- }
-
- public void addActionToCurrentClientProfile(Action newAction) throws CloneNotSupportedException {
- getClientProfile().addAction(newAction);
- }
-
- @Override
- public void saveAction(Action action, boolean runAsync)
- {
- new OnSaveActionTask(
- ClientConnections.getInstance().getClientConnectionBySocketAddress(
- getClient().getRemoteSocketAddress()
- ),
- action,
- displayNameTextField.getText(),
- isCombineChild(),
- !hideDisplayTextCheckBox.isSelected(),
- displayTextColourDefaultCheckBox.isSelected(),
- "#" + displayTextColourPicker.getValue().toString().substring(2),
- clearIconButton.isDisable(),
- !hideIconCheckBox.isSelected(),
- displayTextAlignmentComboBox.getSelectionModel().getSelectedItem(),
- actionBackgroundColourTransparentCheckBox.isSelected(),
- "#" + actionBackgroundColourPicker.getValue().toString().substring(2),
- getCombineActionPropertiesPane(),
- clientProfile, sendIcon, actionBox, actionClientProperties, exceptionAndAlertHandler,
- saveButton, deleteButton, runAsync
- );
- }
-
- @Override
- public void saveAction()
- {
- saveAction(action, true);
- }
-
- public void setFolderButtonVisible(boolean visible)
- {
- openFolderButton.setVisible(visible);
- }
-
- public void validateForm() throws MinorException
- {
- String displayNameStr = displayNameTextField.getText();
-
- StringBuilder finalErrors = new StringBuilder();
-
- if(displayNameStr.isBlank())
- {
- finalErrors.append(" * Display Name cannot be blank\n");
- }
-
- if(!isCombineChild())
- {
- if(action.isHasIcon())
- {
- if(hideDisplayTextCheckBox.isSelected() && hideIconCheckBox.isSelected())
- finalErrors.append(" * Both Icon and display text check box cannot be hidden.\n");
- }
- else
- {
- if(hideDisplayTextCheckBox.isSelected())
- finalErrors.append(" * Display Text cannot be hidden, since there is also no icon.\n");
- }
-
- }
-
-
-
- for (UIPropertyBox clientProperty : actionClientProperties) {
-
- Node controlNode = clientProperty.getControlNode();
-
- if (clientProperty.getControlType() == ControlType.TEXT_FIELD)
- {
- String value = ((TextField) controlNode).getText();
- if(clientProperty.getType() == Type.INTEGER)
- {
- try
- {
- Integer.parseInt(value);
- }
- catch (NumberFormatException e)
- {
- finalErrors.append(" -> ").append(clientProperty.getDisplayName()).append(" must be integer.\n");
- }
- }
- else
- {
- if(value.isBlank() && !clientProperty.isCanBeBlank())
- finalErrors.append(" -> ").append(clientProperty.getDisplayName()).append(" cannot be blank.\n");
- }
- }
- }
-
-
- if(!finalErrors.toString().isEmpty())
- {
- throw new MinorException("You made mistakes",
- finalErrors.toString());
- }
- }
-
- public void onDeleteButtonClicked()
- {
- new OnDeleteActionTask(
- ClientConnections.getInstance().getClientConnectionBySocketAddress(
- getClient().getRemoteSocketAddress()
- ),
- action,
- isCombineChild(),
- getCombineActionPropertiesPane(),
- clientProfile, actionBox, this, exceptionAndAlertHandler,
- !isCombineChild
- );
- }
-}
\ No newline at end of file
D
src/main/java/com/StreamPi/Server/Window/Dashboard/ActionsDetailPane/ActionDetailsPaneListener.java
+0
−26
--- 'a/src/main/java/com/StreamPi/Server/Window/Dashboard/ActionsDetailPane/ActionDetailsPaneListener.java'
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.StreamPi.Server.Window.Dashboard.ActionsDetailPane;
-
-import com.StreamPi.ActionAPI.Action.Action;
-import com.StreamPi.ActionAPI.Action.ActionType;
-import com.StreamPi.ActionAPI.Action.Location;
-import com.StreamPi.ActionAPI.OtherActions.FolderAction;
-import com.StreamPi.Server.Window.Dashboard.ActionGridPane.ActionBox;
-import com.StreamPi.Util.Exception.MinorException;
-import javafx.stage.Window;
-
-public interface ActionDetailsPaneListener {
- void onActionClicked(Action action, ActionBox actionBox) throws MinorException;
-
- void saveAction();
-
- void saveAction(Action action, boolean runAsync);
-
- void clear();
-
- void setSendIcon(boolean sendIcon);
-
- void onOpenFolderButtonClicked();
-
- Window getCurrentWindow();
-
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/Dashboard/ActionsDetailPane/CombineActionPropertiesPane.java'
+++ /dev/null
@@ -1,183 +0,0 @@
-package com.StreamPi.Server.Window.Dashboard.ActionsDetailPane;
-
-import com.StreamPi.ActionAPI.Action.Action;
-import com.StreamPi.ActionAPI.Action.ActionType;
-import com.StreamPi.ActionAPI.Action.Location;
-import com.StreamPi.ActionAPI.ActionProperty.Property.Property;
-import com.StreamPi.ActionAPI.ActionProperty.Property.Type;
-import com.StreamPi.ActionAPI.OtherActions.CombineAction;
-import com.StreamPi.Server.Client.ClientProfile;
-import com.StreamPi.Util.Exception.MinorException;
-import javafx.collections.FXCollections;
-import javafx.collections.ObservableList;
-import javafx.event.ActionEvent;
-import javafx.geometry.Insets;
-import javafx.scene.Node;
-import javafx.scene.control.Button;
-import javafx.scene.control.Label;
-import javafx.scene.input.TransferMode;
-import javafx.scene.layout.HBox;
-import javafx.scene.layout.Priority;
-import javafx.scene.layout.Region;
-import javafx.scene.layout.VBox;
-import javafx.scene.text.Font;
-import org.kordamp.ikonli.javafx.FontIcon;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
-public class CombineActionPropertiesPane extends VBox {
- private CombineAction combineAction;
- private ClientProfile clientProfile;
- private ActionDetailsPane actionDetailsPane;
-
- public CombineAction getCombineAction() {
- return combineAction;
- }
-
- public CombineActionPropertiesPane(CombineAction combineAction, ClientProfile clientProfile, ActionDetailsPane actionDetailsPane) throws MinorException {
- this.combineAction = combineAction;
- this.clientProfile = clientProfile;
- this.actionDetailsPane = actionDetailsPane;
-
- setSpacing(10.0);
-
- setPadding(new Insets(0,0,10,0));
-
- renderProps();
- }
-
-
- public void renderProps() throws MinorException {
-
- getChildren().clear();
-
- int i = 0;
-
- for(String actionID : combineAction.getChildrenIDSequential())
- {
- Action action = clientProfile.getActionByID(actionID);
-
- System.out.println("232323xxxxxxxxxxxx : "+action.getID());
-
- Button settingsButton = new Button();
-
- FontIcon settingsFontIcon = new FontIcon("fas-cog");
- settingsButton.setGraphic(settingsFontIcon);
-
-
- settingsButton.setOnAction(event -> onSettingsButtonClicked(action));
-
- Button upButton = new Button();
- FontIcon upButtonFontIcon = new FontIcon("fas-chevron-up");
- upButton.setGraphic(upButtonFontIcon);
-
-
- Button downButton = new Button();
- FontIcon downButtonFontIcon = new FontIcon("fas-chevron-down");
- downButton.setGraphic(downButtonFontIcon);
-
- Label displayTextLabel = new Label(action.getDisplayText());
- displayTextLabel.setId(action.getID());
-
- Region r = new Region();
- HBox.setHgrow(r, Priority.ALWAYS);
-
- HBox actionHBox = new HBox(displayTextLabel, r, settingsButton, upButton, downButton);
- actionHBox.setSpacing(5.0);
-
- upButton.setUserData(i);
- downButton.setUserData(i);
-
-
- upButton.setOnAction(this::onUpButtonClicked);
-
- downButton.setOnAction(this::onDownButtonClicked);
-
- System.out.println("67878678678678");
- getChildren().add(actionHBox);
- System.out.println("9mhmmn");
- i++;
- }
- }
-
- public void onSettingsButtonClicked(Action action)
- {
- actionDetailsPane.clear();
- actionDetailsPane.setAction(action);
- try {
- actionDetailsPane.renderActionProperties();
- } catch (MinorException e) {
- e.printStackTrace();
- }
- }
-
- public void onUpButtonClicked(ActionEvent event) {
- try {
- Node node = (Node) event.getSource();
-
- int currentIndex = (int) node.getUserData();
-
- if(currentIndex > 0)
- {
-
- Property current = combineAction.getClientProperties().getSingleProperty(currentIndex+"");
- Property aboveOne = combineAction.getClientProperties().getSingleProperty((currentIndex-1)+"");
-
- combineAction.addChild(current.getRawValue(), currentIndex-1);
- combineAction.addChild(aboveOne.getRawValue(), currentIndex);
-
- actionDetailsPane.saveAction();
- renderProps();
- }
- }
- catch (MinorException e)
- {
- e.printStackTrace();
- }
- }
-
-
- public void onDownButtonClicked(ActionEvent event)
- {
- try {
- Node node = (Node) event.getSource();
-
- int currentIndex = (int) node.getUserData();
-
- if(currentIndex < getChildren().size() - 1)
- {
-
- Property current = combineAction.getClientProperties().getSingleProperty(currentIndex+"");
- Property belowOne = combineAction.getClientProperties().getSingleProperty((currentIndex+1)+"");
-
- combineAction.addChild(current.getRawValue(), currentIndex+1);
- combineAction.addChild(belowOne.getRawValue(), currentIndex);
-
- actionDetailsPane.saveAction();
- renderProps();
- }
- }
- catch (MinorException e)
- {
- e.printStackTrace();
- }
- }
-
-
- public List<String> getFinalChildren()
- {
- ArrayList<String> children = new ArrayList<>();
-
- for(int i = 0;i<getChildren().size();i++)
- {
- HBox hBox = (HBox) getChildren().get(i);
- Label label = (Label) hBox.getChildren().get(0);
- children.add(label.getId());
- }
-
- return children;
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/Dashboard/ActionsDetailPane/OnDeleteActionTask.java'
+++ /dev/null
@@ -1,121 +0,0 @@
-package com.StreamPi.Server.Window.Dashboard.ActionsDetailPane;
-
-import java.util.logging.Logger;
-
-import com.StreamPi.ActionAPI.Action.Action;
-import com.StreamPi.ActionAPI.ActionProperty.Property.Property;
-import com.StreamPi.Server.Client.ClientProfile;
-import com.StreamPi.Server.Connection.ClientConnection;
-import com.StreamPi.Server.Window.ExceptionAndAlertHandler;
-import com.StreamPi.Server.Window.Dashboard.ActionGridPane.ActionBox;
-import com.StreamPi.Util.Exception.MinorException;
-import com.StreamPi.Util.Exception.SevereException;
-
-import javafx.application.Platform;
-import javafx.concurrent.Task;
-
-public class OnDeleteActionTask extends Task<Void>
-{
- private Logger logger;
-
- public OnDeleteActionTask(ClientConnection connection, Action action, boolean isCombineChild,
- CombineActionPropertiesPane combineActionPropertiesPane, ClientProfile clientProfile, ActionBox actionBox,
- ActionDetailsPane actionDetailsPane,
- ExceptionAndAlertHandler exceptionAndAlertHandler, boolean runAsync)
- {
- this.connection = connection;
- this.action = action;
- this.isCombineChild = isCombineChild;
- this.combineActionPropertiesPane = combineActionPropertiesPane;
- this.clientProfile = clientProfile;
- this.actionBox = actionBox;
- this.actionDetailsPane = actionDetailsPane;
- this.exceptionAndAlertHandler = exceptionAndAlertHandler;
-
- logger = Logger.getLogger(getClass().getName());
-
- if(runAsync)
- new Thread(this).start();
- else
- runTask();
- }
-
- private ClientConnection connection;
- private Action action;
- private ActionBox actionBox;
- private ActionDetailsPane actionDetailsPane;
- private boolean isCombineChild;
- private ClientProfile clientProfile;
- private CombineActionPropertiesPane combineActionPropertiesPane;
- private ExceptionAndAlertHandler exceptionAndAlertHandler;
-
-
- private void runTask()
- {
- try {
-
- connection.deleteAction(clientProfile.getID(), action.getID());
- clientProfile.removeActionByID(action.getID());
-
- if(isCombineChild)
- {
- System.out.println("ACTION ID TO BE REMOVED : "+action.getID());
- combineActionPropertiesPane.getCombineAction().removeChild(action.getID());
-
- System.out.println("222155 "+combineActionPropertiesPane.getCombineAction().getClientProperties().getSize());
-
- combineActionPropertiesPane.renderProps();
-
- try {
-
-
- actionDetailsPane.saveAction(combineActionPropertiesPane.getCombineAction(), false);
-
- System.out.println(combineActionPropertiesPane.getCombineAction().getDisplayText()+"@#@#@#@#@#@#");
- actionDetailsPane.onActionClicked(
- combineActionPropertiesPane.getCombineAction(),
- actionBox
- );
-
-
-
- } catch (MinorException e) {
- e.printStackTrace();
- }
- }
- else
- {
- Platform.runLater(()->{
- actionBox.clear();
- actionDetailsPane.clear();
- });
- }
-
-
- // Platform.runLater(()->{
- // saveButton.setDisable(false);
- // deleteButton.setDisable(false);
- // });
-
- }
- catch (SevereException e)
- {
- e.printStackTrace();
- exceptionAndAlertHandler.handleSevereException(e);
- }
- catch (MinorException e)
- {
- e.printStackTrace();
- exceptionAndAlertHandler.handleMinorException(e);
- }
- }
-
-
- @Override
- protected Void call() throws Exception
- {
- runTask();
- return null;
- }
-
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/Dashboard/ActionsDetailPane/OnSaveActionTask.java'
+++ /dev/null
@@ -1,234 +0,0 @@
-package com.StreamPi.Server.Window.Dashboard.ActionsDetailPane;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.logging.Logger;
-
-import com.StreamPi.ActionAPI.Action.Action;
-import com.StreamPi.ActionAPI.Action.ActionType;
-import com.StreamPi.ActionAPI.Action.DisplayTextAlignment;
-import com.StreamPi.ActionAPI.ActionProperty.ClientProperties;
-import com.StreamPi.ActionAPI.ActionProperty.Property.Property;
-import com.StreamPi.ActionAPI.ActionProperty.Property.Type;
-import com.StreamPi.Server.Client.ClientProfile;
-import com.StreamPi.Server.Connection.ClientConnection;
-import com.StreamPi.Server.UIPropertyBox.UIPropertyBox;
-import com.StreamPi.Server.Window.ExceptionAndAlertHandler;
-import com.StreamPi.Server.Window.Dashboard.ActionGridPane.ActionBox;
-import com.StreamPi.Util.Exception.SevereException;
-
-import javafx.application.Platform;
-import javafx.concurrent.Task;
-import javafx.scene.control.Button;
-
-public class OnSaveActionTask extends Task<Void>
-{
-
- private Logger logger;
-
-
- public OnSaveActionTask(ClientConnection connection, Action action, String displayNameText, boolean isCombineChild,
- boolean isShowDisplayText, boolean isDefaultDisplayTextColour, String displayTextFontColour, boolean isClearIcon,
- boolean isHideIcon, DisplayTextAlignment displayTextAlignment, boolean isTransparentBackground, String backgroundColour,
- CombineActionPropertiesPane combineActionPropertiesPane, ClientProfile clientProfile, boolean sendIcon, ActionBox actionBox,
- ArrayList<UIPropertyBox> actionClientProperties, ExceptionAndAlertHandler exceptionAndAlertHandler, Button saveButton, Button deleteButton,
- boolean runAsync)
- {
- this.saveButton = saveButton;
- this.deleteButton = deleteButton;
-
- this.connection = connection;
- this.action = action;
- this.displayNameText = displayNameText;
- this.isCombineChild = isCombineChild;
- this.isShowDisplayText = isShowDisplayText;
- this.isDefaultDisplayTextColour = isDefaultDisplayTextColour;
- this.displayTextFontColour = displayTextFontColour;
- this.isClearIcon = isClearIcon;
- this.isHideIcon = isHideIcon;
- this.displayTextAlignment = displayTextAlignment;
- this.isTransparentBackground = isTransparentBackground;
- this.combineActionPropertiesPane = combineActionPropertiesPane;
- this.clientProfile = clientProfile;
- this.sendIcon = sendIcon;
- this.actionBox = actionBox;
- this.exceptionAndAlertHandler = exceptionAndAlertHandler;
- this.backgroundColour = backgroundColour;
- this.actionClientProperties = actionClientProperties;
-
-
- logger = Logger.getLogger(getClass().getName());
-
-
- if(runAsync)
- new Thread(this).start();
- else
- runTask();
- }
-
- private Button saveButton;
- private Button deleteButton;
- private boolean isShowDisplayText;
- private boolean isCombineChild;
- private String displayNameText;
- private boolean isDefaultDisplayTextColour;
- private ArrayList<UIPropertyBox> actionClientProperties;
- private String displayTextFontColour;
- private boolean isClearIcon;
- private boolean isHideIcon;
- private DisplayTextAlignment displayTextAlignment;
- private boolean isTransparentBackground;
- private String backgroundColour;
- private CombineActionPropertiesPane combineActionPropertiesPane;
- private ClientProfile clientProfile;
- private boolean sendIcon;
- private ActionBox actionBox;
- private ExceptionAndAlertHandler exceptionAndAlertHandler;
- private Action action;
- private ClientConnection connection;
-
- private void setSaveDeleteButtonState(boolean state)
- {
- Platform.runLater(()->{
- saveButton.setDisable(state);
- deleteButton.setDisable(state);
- });
- }
-
-
- private void runTask()
- {
- action.setDisplayText(displayNameText);
-
- if(!isCombineChild)
- {
- setSaveDeleteButtonState(true);
-
- action.setShowDisplayText(isShowDisplayText);
-
- if(isDefaultDisplayTextColour)
- action.setDisplayTextFontColourHex("");
- else
- {
- action.setDisplayTextFontColourHex(displayTextFontColour);
- //String fontColour = "#" + displayTextColourPicker.getValue().toString().substring(2);
- //action.setDisplayTextFontColourHex(fontColour);
- }
-
-
- if(isClearIcon)
- {
- action.setIcon(null);
- action.setHasIcon(false);
- action.setShowIcon(false);
- }
-
- if(action.isHasIcon())
- action.setShowIcon(isHideIcon);
-
-
- action.setDisplayTextAlignment(displayTextAlignment);
-
-
- logger.info("BBBGGG : "+backgroundColour);
- if(isTransparentBackground)
- action.setBgColourHex("");
- else
- {
- //String bgColour = "#" + actionBackgroundColourPicker.getValue().toString().substring(2);
- action.setBgColourHex(backgroundColour);
- }
- }
-
- System.out.println("parent : "+action.getParent());
-
-
- if(action.getActionType() == ActionType.COMBINE)
- {
- List<String> finalChildren = combineActionPropertiesPane.getFinalChildren();
- System.out.println("2334 "+finalChildren.size());
-
- ClientProperties clientProperties = new ClientProperties();
-
- for(int i = 0;i<finalChildren.size();i++)
- {
- Property property = new Property(i+"", Type.STRING);
- property.setRawValue(finalChildren.get(i));
-
- clientProperties.addProperty(property);
- }
-
- action.getClientProperties().set(clientProperties);
- }
- else
- {
- //properties
- for (UIPropertyBox clientProperty : actionClientProperties) {
- action.getClientProperties().get().get(clientProperty.getIndex()).setRawValue(clientProperty.getRawValue());
- }
- }
-
-
- try
- {
- logger.info("Saving action ... "+action.isHasIcon()+"+"+sendIcon);
-
- /*if(action.isHasIcon())
- {
- if(clientProfile.getActionByID(action.getID()).getIconAsByteArray() == null)
- {
- sendIcon = true;
- }
- else
- {
- if(!Arrays.equals(action.getIconAsByteArray(), clientProfile.getActionByID(action.getID()).getIconAsByteArray()))
- {
- logger.info("Sending ...");
- sendIcon = true;
- }
- }
- }*/
-
- connection.saveActionDetails(clientProfile.getID(), action);
-
- if(sendIcon)
- {
- connection.sendIcon(clientProfile.getID(), action.getID(), action.getIconAsByteArray());
- }
-
- if(!isCombineChild)
- {
- Platform.runLater(()->{
- actionBox.clear();
- actionBox.setAction(action);
- actionBox.baseInit();
- actionBox.init();
- });
-
- setSaveDeleteButtonState(false);
- }
-
- clientProfile.removeActionByID(action.getID());
- clientProfile.addAction(action);
-
- }
- catch (SevereException e)
- {
- e.printStackTrace();
- exceptionAndAlertHandler.handleSevereException(e);
- }
- catch (CloneNotSupportedException e)
- {
- e.printStackTrace();
- }
-
- }
-
- @Override
- protected Void call() throws Exception
- {
- runTask();
- return null;
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/Dashboard/ClientDetailsPane.java'
+++ /dev/null
@@ -1,167 +0,0 @@
-package com.StreamPi.Server.Window.Dashboard;
-
-import com.StreamPi.Server.Client.Client;
-import com.StreamPi.Server.Client.ClientProfile;
-import com.StreamPi.Server.Connection.ClientConnection;
-import com.StreamPi.Server.Connection.ClientConnections;
-import javafx.application.Platform;
-import javafx.collections.FXCollections;
-import javafx.geometry.Insets;
-import javafx.scene.CacheHint;
-import javafx.scene.control.*;
-import javafx.scene.layout.HBox;
-import javafx.scene.layout.Priority;
-import javafx.scene.layout.Region;
-import javafx.scene.layout.VBox;
-import javafx.scene.paint.Paint;
-import javafx.util.Callback;
-import org.kordamp.ikonli.javafx.FontIcon;
-
-public class ClientDetailsPane extends HBox {
-
- private DashboardInterface dashboard;
-
- public ClientDetailsPane(DashboardInterface dashboard)
- {
- this.dashboard = dashboard;
-
- VBox.setVgrow(this, Priority.NEVER);
- getStyleClass().add("client_details_pane");
- setPadding(new Insets(10));
- setMinHeight(90);
-
- initUI();
- loadData();
-
- setCache(true);
- setCacheHint(CacheHint.SPEED);
- }
-
- private ComboBox<ClientConnection> clientsComboBox;
- private Label noClientsConnectedLabel;
- private ComboBox<ClientProfile> clientProfilesComboBox;
-
-
- public void initUI()
- {
- noClientsConnectedLabel = new Label("No Clients Connected");
- noClientsConnectedLabel.managedProperty().bind(noClientsConnectedLabel.visibleProperty());
-
- clientsComboBox = new ComboBox<>();
- clientsComboBox.setPromptText("Choose Client");
-
- clientsComboBox.valueProperty().addListener((observableValue, oldVal, newVal) -> {
- if(oldVal!=newVal && newVal!=null)
- {
- dashboard.newSelectedClientConnection(newVal);
- clientProfilesComboBox.setItems(FXCollections.observableArrayList(newVal.getClient().getAllClientProfiles()));
- clientProfilesComboBox.setVisible(true);
- }
- });
-
- clientsComboBox.managedProperty().bind(clientsComboBox.visibleProperty());
-
-
- Callback<ListView<ClientConnection>, ListCell<ClientConnection>> clientsComboBoxFactory = new Callback<>() {
- @Override
- public ListCell<ClientConnection> call(ListView<ClientConnection> clientConnectionListView) {
-
- return new ListCell<>() {
- @Override
- protected void updateItem(ClientConnection clientConnection, boolean b) {
- super.updateItem(clientConnection, b);
-
- if(clientConnection == null)
- {
- setText("Choose Client");
- }
- else
- {
- Client client = clientConnection.getClient();
- setText(client.getNickName());
- }
- }
- };
- }
- };
- clientsComboBox.setCellFactory(clientsComboBoxFactory);
- clientsComboBox.setButtonCell(clientsComboBoxFactory.call(null));
-
-
-
- clientProfilesComboBox = new ComboBox<>();
- clientProfilesComboBox.setPromptText("Choose Profile");
- clientProfilesComboBox.valueProperty().addListener((observableValue, oldVal, newVal) -> {
- if(oldVal!=newVal && newVal!=null)
- {
- dashboard.newSelectedClientProfile(newVal);
- }
- });
-
-
- clientProfilesComboBox.managedProperty().bind(clientProfilesComboBox.visibleProperty());
- Callback<ListView<ClientProfile>, ListCell<ClientProfile>> clientProfilesComboBoxFactory = new Callback<ListView<ClientProfile>, ListCell<ClientProfile>>() {
- @Override
- public ListCell<ClientProfile> call(ListView<ClientProfile> clientProfileListView) {
- return new ListCell<>()
- {
- @Override
- protected void updateItem(ClientProfile profile, boolean b) {
- super.updateItem(profile, b);
-
- if(profile == null)
- {
- setText("Choose Profile");
- }
- else
- {
- setText(profile.getName());
- }
- }
- };
- }
- };
- clientProfilesComboBox.setCellFactory(clientProfilesComboBoxFactory);
- clientProfilesComboBox.setButtonCell(clientProfilesComboBoxFactory.call(null));
-
- VBox stack = new VBox(noClientsConnectedLabel, clientsComboBox, clientProfilesComboBox);
- stack.setSpacing(10);
-
- getChildren().addAll(stack);
-
- }
-
-
- private void loadData()
- {
- clientsComboBox.getSelectionModel().clearSelection();
- clientProfilesComboBox.getSelectionModel().clearSelection();
-
- if(ClientConnections.getInstance().getConnections().size() == 0)
- {
- noClientsConnectedLabel.setVisible(true);
-
- clientsComboBox.setVisible(false);
-
- clientProfilesComboBox.setVisible(false);
-
-
- dashboard.newSelectedClientConnection(null);
-
- }
- else
- {
- noClientsConnectedLabel.setVisible(false);
-
- clientsComboBox.setVisible(true);
- clientProfilesComboBox.setVisible(false);
-
- clientsComboBox.setItems(FXCollections.observableArrayList(ClientConnections.getInstance().getConnections()));
- }
- }
-
- public void refresh()
- {
- loadData();
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/Dashboard/DashboardBase.java'
+++ /dev/null
@@ -1,134 +0,0 @@
-package com.StreamPi.Server.Window.Dashboard;
-
-import java.util.logging.Logger;
-
-import com.StreamPi.ActionAPI.Action.Action;
-import com.StreamPi.Server.Client.ClientProfile;
-import com.StreamPi.Server.Connection.ClientConnection;
-import com.StreamPi.Server.Window.Dashboard.ActionGridPane.ActionGridPane;
-import com.StreamPi.Server.Window.Dashboard.ActionsDetailPane.ActionDetailsPane;
-import com.StreamPi.Server.Window.ExceptionAndAlertHandler;
-import com.StreamPi.Util.Exception.SevereException;
-import javafx.application.HostServices;
-import javafx.scene.CacheHint;
-import javafx.scene.layout.HBox;
-import javafx.scene.layout.Priority;
-import javafx.scene.layout.VBox;
-
-public class DashboardBase extends HBox implements DashboardInterface {
-
- private final VBox leftPane;
-
- private Logger logger;
-
- public ClientProfile currentClientProfile;
-
- private ExceptionAndAlertHandler exceptionAndAlertHandler;
-
-
- public DashboardBase(ExceptionAndAlertHandler exceptionAndAlertHandler, HostServices hostServices)
- {
- this.exceptionAndAlertHandler = exceptionAndAlertHandler;
- logger = Logger.getLogger(DashboardBase.class.getName());
- leftPane = new VBox();
-
- HBox.setHgrow(leftPane, Priority.ALWAYS);
- getChildren().add(leftPane);
-
- setPluginsPane(new PluginsPane(hostServices));
-
- setClientDetailsPane(new ClientDetailsPane(this));
-
- setActionGridPane(new ActionGridPane(exceptionAndAlertHandler));
-
- setActionDetailsPane(new ActionDetailsPane(exceptionAndAlertHandler, hostServices));
-
- getActionGridPane().setActionDetailsPaneListener(getActionDetailsPane());
- }
-
-
-
- private PluginsPane pluginsPane;
- private void setPluginsPane(PluginsPane pluginsPane)
- {
- this.pluginsPane = pluginsPane;
- getChildren().add(this.pluginsPane);
- }
- public PluginsPane getPluginsPane()
- {
- return pluginsPane;
- }
-
- private ClientDetailsPane clientDetailsPane;
- private void setClientDetailsPane(ClientDetailsPane clientDetailsPane)
- {
- this.clientDetailsPane = clientDetailsPane;
- leftPane.getChildren().add(this.clientDetailsPane);
- }
- public ClientDetailsPane getClientDetailsPane()
- {
- return clientDetailsPane;
- }
-
- private ActionGridPane actionGridPane;
- private void setActionGridPane(ActionGridPane actionGridPane)
- {
- this.actionGridPane = actionGridPane;
- leftPane.getChildren().add(this.actionGridPane);
- }
- public ActionGridPane getActionGridPane()
- {
- return actionGridPane;
- }
-
- private ActionDetailsPane actionDetailsPane;
- private void setActionDetailsPane(ActionDetailsPane actionDetailsPane)
- {
- this.actionDetailsPane = actionDetailsPane;
- leftPane.getChildren().add(this.actionDetailsPane);
- }
- public ActionDetailsPane getActionDetailsPane()
- {
- return actionDetailsPane;
- }
-
- public void newSelectedClientConnection(ClientConnection clientConnection)
- {
- if(clientConnection == null)
- {
- logger.info("Remove action grid");
- }
- else
- {
- getActionDetailsPane().setClient(clientConnection.getClient());
- getActionGridPane().setClient(clientConnection.getClient());
- }
- }
-
- public void newSelectedClientProfile(ClientProfile clientProfile)
- {
- this.currentClientProfile = clientProfile;
-
- getActionDetailsPane().setClientProfile(clientProfile);
-
- drawProfile(this.currentClientProfile);
- }
-
- public void drawProfile(ClientProfile clientProfile)
- {
- logger.info("Drawing ...");
-
- getActionGridPane().setClientProfile(clientProfile);
-
- try {
- getActionGridPane().renderGrid();
- getActionGridPane().renderActions();
- }
- catch (SevereException e)
- {
- exceptionAndAlertHandler.handleSevereException(e);
- }
-
-
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/Dashboard/DashboardInterface.java'
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.StreamPi.Server.Window.Dashboard;
-
-import com.StreamPi.Server.Client.ClientProfile;
-import com.StreamPi.Server.Connection.ClientConnection;
-
-public interface DashboardInterface {
- void newSelectedClientConnection(ClientConnection clientConnection);
- void newSelectedClientProfile(ClientProfile clientProfile);
-
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/Dashboard/DonatePopupContent.java'
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.StreamPi.Server.Window.Dashboard;
-
-import com.StreamPi.Server.IO.Config;
-import com.StreamPi.Server.Window.ExceptionAndAlertHandler;
-import com.StreamPi.Util.Alert.StreamPiAlert;
-import com.StreamPi.Util.Alert.StreamPiAlertListener;
-import com.StreamPi.Util.Alert.StreamPiAlertType;
-import com.StreamPi.Util.Exception.MinorException;
-import com.StreamPi.Util.Exception.SevereException;
-
-import javafx.application.HostServices;
-import javafx.scene.control.CheckBox;
-import javafx.scene.control.Hyperlink;
-import javafx.scene.control.Label;
-import javafx.scene.layout.VBox;
-
-public class DonatePopupContent{
- public DonatePopupContent(HostServices hostServices, ExceptionAndAlertHandler exceptionAndAlertHandler)
- {
- Label label = new Label("We are a very small team working very hard on this project for best user experience.\n\n" +
- "Something like StreamPi takes time, effort and resources. But we will always keep this 100% opensource and free.\n\n" +
- "If you find this project helpful, and would want to help us, please consider donating :)\n\n"+
- "If you are unable to do so even a small shoutout and share across social media would be very helpful.");
-
- label.setWrapText(true);
- label.getStyleClass().add("donate_request_popup_label");
-
- Hyperlink patreonLink = new Hyperlink("Our Patreon");
- patreonLink.setOnAction(event ->{
- hostServices.showDocument("https://patreon.com/streampi");
- });
- patreonLink.getStyleClass().add("donate_request_popup_patreon_link");
-
- VBox pane = new VBox(label, patreonLink);
- pane.setSpacing(5.0);
-
- streamPiAlert = new StreamPiAlert("Hey!", StreamPiAlertType.INFORMATION, pane);
-
- streamPiAlert.setOnClicked(new StreamPiAlertListener()
- {
- @Override
- public void onClick(String buttonClicked)
- {
- try
- {
- Config.getInstance().setAllowDonatePopup(false);
- Config.getInstance().save();
- }
- catch(SevereException e)
- {
- exceptionAndAlertHandler.handleSevereException(e);
- }
- }
-
- });
- }
-
- private StreamPiAlert streamPiAlert;
-
- public void show()
- {
- streamPiAlert.show();
- }
-
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/Dashboard/PluginsPane.java'
+++ /dev/null
@@ -1,265 +0,0 @@
-package com.StreamPi.Server.Window.Dashboard;
-
-import com.StreamPi.ActionAPI.Action.Action;
-import com.StreamPi.ActionAPI.Action.ActionType;
-import com.StreamPi.ActionAPI.Action.DisplayTextAlignment;
-import com.StreamPi.ActionAPI.ActionProperty.Property.Property;
-import com.StreamPi.ActionAPI.ActionProperty.Property.Type;
-import com.StreamPi.ActionAPI.NormalAction.NormalAction;
-import com.StreamPi.ActionAPI.OtherActions.CombineAction;
-import com.StreamPi.ActionAPI.OtherActions.FolderAction;
-import com.StreamPi.Server.Action.NormalActionPlugins;
-
-import javafx.application.HostServices;
-import javafx.event.EventHandler;
-import javafx.geometry.Insets;
-import javafx.geometry.Pos;
-import javafx.scene.CacheHint;
-import javafx.scene.Node;
-import javafx.scene.control.*;
-import javafx.scene.image.ImageView;
-import javafx.scene.input.ClipboardContent;
-import javafx.scene.input.Dragboard;
-import javafx.scene.input.MouseEvent;
-import javafx.scene.input.TransferMode;
-import javafx.scene.layout.*;
-import javafx.scene.paint.Paint;
-import org.kordamp.ikonli.javafx.FontIcon;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-public class PluginsPane extends VBox {
-
- private Button settingsButton;
-
- public PluginsPane(HostServices hostServices)
- {
- setMinWidth(250);
- getStyleClass().add("plugins_pane");
- setPadding(new Insets(10));
-
- setSpacing(10.0);
-
- this.hostServices = hostServices;
-
- initUI();
- }
-
- private Accordion pluginsAccordion;
-
- public void initUI()
- {
- pluginsAccordion = new Accordion();
- pluginsAccordion.setCache(true);
-
- Region r = new Region();
- VBox.setVgrow(r, Priority.ALWAYS);
-
- settingsButton = new Button();
-
- FontIcon cog = new FontIcon("fas-cog");
-
- settingsButton.setGraphic(cog);
-
- HBox settingsHBox = new HBox(settingsButton);
- settingsHBox.setAlignment(Pos.CENTER_RIGHT);
-
- getChildren().addAll(new Label("Plugins"), pluginsAccordion, r, settingsHBox);
- }
-
- public Button getSettingsButton()
- {
- return settingsButton;
- }
-
- public void clearData()
- {
- pluginsAccordion.getPanes().clear();
- }
-
- public void loadData()
- {
- HashMap<String, ArrayList<NormalAction>> sortedPlugins = NormalActionPlugins.getInstance().getSortedPlugins();
-
- for(String eachCategory : sortedPlugins.keySet())
- {
- VBox vBox = new VBox();
- vBox.setSpacing(5);
-
-
- TitledPane pane = new TitledPane(eachCategory, vBox);
- for(NormalAction eachAction : sortedPlugins.get(eachCategory))
- {
- if(!eachAction.isVisibleInPluginsPane())
- continue;
-
- Button eachNormalActionPluginButton = new Button();
- HBox.setHgrow(eachNormalActionPluginButton, Priority.ALWAYS);
- eachNormalActionPluginButton.setMaxWidth(Double.MAX_VALUE);
- eachNormalActionPluginButton.setAlignment(Pos.CENTER_LEFT);
-
- Node graphic = eachAction.getServerButtonGraphic();
-
- if(graphic == null)
- {
- FontIcon cogs = new FontIcon("fas-cogs");
- cogs.getStyleClass().add("dashboard_plugins_pane_action_icon");
- eachNormalActionPluginButton.setGraphic(cogs);
- }
- else
- {
- if(graphic instanceof FontIcon)
- {
- FontIcon fi = (FontIcon) graphic;
- eachNormalActionPluginButton.setGraphic(fi);
- }
- else if(graphic instanceof ImageView)
- {
- ImageView iv = (ImageView) graphic;
- iv.getStyleClass().add("dashboard_plugins_pane_action_icon_imageview");
- iv.setPreserveRatio(false);
- eachNormalActionPluginButton.setGraphic(iv);
- }
- }
- eachNormalActionPluginButton.setText(eachAction.getName());
-
-
- eachNormalActionPluginButton.setOnDragDetected(mouseEvent -> {
- Dragboard db = eachNormalActionPluginButton.startDragAndDrop(TransferMode.ANY);
-
- ClipboardContent content = new ClipboardContent();
-
- content.put(Action.getDataFormat(), createFakeAction(eachAction, "Untitled Action"));
-
- db.setContent(content);
-
- mouseEvent.consume();
- });
-
-
-
- HBox hBox = new HBox(eachNormalActionPluginButton);
- hBox.setSpacing(5.0);
- hBox.setAlignment(Pos.TOP_LEFT);
-
- HBox.setHgrow(eachNormalActionPluginButton, Priority.ALWAYS);
-
- if(eachAction.getHelpLink() != null) {
- Button helpButton = new Button();
- FontIcon questionIcon = new FontIcon("fas-question");
- questionIcon.getStyleClass().add("dashboard_plugins_pane_action_help_icon");
- helpButton.setGraphic(questionIcon);
- helpButton.setOnAction(event -> hostServices.showDocument(eachAction.getHelpLink()));
-
- hBox.getChildren().add(helpButton);
- }
-
-
- vBox.getChildren().add(hBox);
- }
-
- if(vBox.getChildren().size() > 0)
- pluginsAccordion.getPanes().add(pane);
- }
- }
-
-
- private HostServices hostServices;
-
- public Action createFakeAction(Action action, String displayText)
- {
- Action newAction = new Action(action.getActionType());
-
- if(action.getActionType() == ActionType.NORMAL)
- {
- newAction.setModuleName(action.getModuleName());
- newAction.setVersion(action.getVersion());
- newAction.setName(action.getName());
- }
-
- newAction.setClientProperties(action.getClientProperties());
-
- for(Property property : newAction.getClientProperties().get())
- {
- if(property.getType() == Type.STRING || property.getType() == Type.INTEGER || property.getType() == Type.DOUBLE)
- property.setRawValue(property.getDefaultRawValue());
- }
-
- // newAction.setLocation(location);
-
- newAction.setIDRandom();
-
-
- newAction.setShowDisplayText(true);
- newAction.setDisplayText(displayText);
- newAction.setDisplayTextAlignment(DisplayTextAlignment.CENTER);
- newAction.setShowIcon(false);
- newAction.setHasIcon(false);
-
- //action.setParent(root);
-
- newAction.setBgColourHex("");
- newAction.setDisplayTextFontColourHex("");
-
- return newAction;
- }
-
- public void loadOtherActions()
- {
- VBox vBox = new VBox();
-
- Button folderActionButton = new Button("Folder");
- folderActionButton.setMaxWidth(Double.MAX_VALUE);
- folderActionButton.setAlignment(Pos.CENTER_LEFT);
- FontIcon folder = new FontIcon("fas-folder");
- folderActionButton.setGraphic(folder);
-
- folderActionButton.setOnDragDetected(mouseEvent -> {
- Dragboard db = folderActionButton.startDragAndDrop(TransferMode.ANY);
-
- ClipboardContent content = new ClipboardContent();
-
- content.put(Action.getDataFormat(), createFakeAction(new FolderAction(), "Untitled Folder"));
-
- db.setContent(content);
-
- mouseEvent.consume();
- });
-
-
-
-
- Button combineActionButton = new Button("Combine");
- combineActionButton.setMaxWidth(Double.MAX_VALUE);
- combineActionButton.setAlignment(Pos.CENTER_LEFT);
- FontIcon list = new FontIcon("fas-list");
- combineActionButton.setGraphic(list);
-
- combineActionButton.setOnDragDetected(mouseEvent -> {
- Dragboard db = combineActionButton.startDragAndDrop(TransferMode.ANY);
-
- ClipboardContent content = new ClipboardContent();
-
- content.put(Action.getDataFormat(), createFakeAction(new CombineAction(), "Untitled Combine"));
-
- db.setContent(content);
-
- mouseEvent.consume();
- });
-
-
-
-
-
- vBox.getChildren().addAll(folderActionButton, combineActionButton);
- vBox.setSpacing(5);
-
- TitledPane pane = new TitledPane("StreamPi", vBox);
-
- pluginsAccordion.getPanes().add(pane);
- pluginsAccordion.setCache(true);
- pluginsAccordion.setCacheHint(CacheHint.SPEED);
- }
-
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/ExceptionAndAlertHandler.java'
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.StreamPi.Server.Window;
-
-import com.StreamPi.Util.Alert.StreamPiAlertType;
-import com.StreamPi.Util.Exception.MinorException;
-import com.StreamPi.Util.Exception.SevereException;
-import javafx.scene.control.Alert;
-
-public interface ExceptionAndAlertHandler {
- void handleMinorException(MinorException e);
- void handleSevereException(SevereException e);
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/FirstTimeUse/FinalConfigPane.java'
+++ /dev/null
@@ -1,108 +0,0 @@
-package com.StreamPi.Server.Window.FirstTimeUse;
-
-import com.StreamPi.Server.Connection.ServerListener;
-import com.StreamPi.Server.IO.Config;
-import com.StreamPi.Server.Window.ExceptionAndAlertHandler;
-import com.StreamPi.Util.Exception.SevereException;
-import com.StreamPi.Util.FormHelper.HBoxInputBox;
-import com.StreamPi.Util.FormHelper.SpaceFiller;
-import com.StreamPi.Util.FormHelper.SpaceFiller.FillerType;
-
-import javafx.geometry.Pos;
-import javafx.scene.control.Alert;
-import javafx.scene.control.Button;
-import javafx.scene.control.Label;
-import javafx.scene.control.TextField;
-import javafx.scene.control.Alert.AlertType;
-import javafx.scene.layout.HBox;
-import javafx.scene.layout.VBox;
-import javafx.stage.Stage;
-
-public class FinalConfigPane extends VBox
-{
- private TextField serverNicknameTextField;
- private TextField serverPortTextField;
-
- private ExceptionAndAlertHandler exceptionAndAlertHandler;
- private ServerListener serverListener;
-
- public FinalConfigPane(ExceptionAndAlertHandler exceptionAndAlertHandler, ServerListener serverListener)
- {
- this.exceptionAndAlertHandler = exceptionAndAlertHandler;
- this.serverListener = serverListener;
-
- getStyleClass().add("first_time_use_pane_final_config");
-
- Label label = new Label("Thats it. Now just name your Stream-Pi Server, and the port where the server will run on!\n" +
- "You can leave the default value of the port as it is.");
- label.setWrapText(true);
- label.getStyleClass().add("first_time_use_pane_final_config_label");
-
- serverNicknameTextField = new TextField();
- serverPortTextField = new TextField("2004");
-
- HBoxInputBox serverNickNameInputBox = new HBoxInputBox("Server Nickname", serverNicknameTextField, 200);
- HBoxInputBox serverPortInputBox = new HBoxInputBox("Server Port", serverPortTextField);
-
- Button confirmButton = new Button("Confirm");
- confirmButton.setOnAction(event -> onConfirmButtonClicked());
- HBox bBar = new HBox(confirmButton);
- bBar.setAlignment(Pos.CENTER_RIGHT);
-
- getChildren().addAll(label, serverNickNameInputBox, serverPortInputBox, new SpaceFiller(FillerType.VBox), bBar);
-
- setSpacing(10.0);
-
- setVisible(false);
- }
-
- private void onConfirmButtonClicked()
- {
- StringBuilder errors = new StringBuilder();
-
- String serverNameStr = serverNicknameTextField.getText();
- String serverPortStr = serverPortTextField.getText();
-
- if(serverNameStr.isBlank() || serverNameStr.isEmpty())
- {
- errors.append("* Server Name cannot be blank.\n");
- }
-
- int serverPort=-1;
- try {
- serverPort = Integer.parseInt(serverPortStr);
-
- if (serverPort < 1024)
- errors.append("* Server Port must be more than 1024");
- }
- catch (NumberFormatException e)
- {
- errors.append("* Server Port must be integer.\n");
- }
-
- if(errors.toString().isEmpty())
- {
- try
- {
- Config.getInstance().setServerName(serverNameStr);
- Config.getInstance().setServerPort(serverPort);
- Config.getInstance().setFirstTimeUse(false);
- Config.getInstance().save();
-
- serverListener.othInit();
-
- ((Stage) getScene().getWindow()).close();
- }
- catch(SevereException e)
- {
- exceptionAndAlertHandler.handleSevereException(e);
- }
- }
- else
- {
- Alert alert = new Alert(AlertType.ERROR);
- alert.setContentText("Please rectify the following errors and try again:\n"+errors.toString());
- alert.show();
- }
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/FirstTimeUse/FirstTimeUse.java'
+++ /dev/null
@@ -1,146 +0,0 @@
-package com.StreamPi.Server.Window.FirstTimeUse;
-
-import com.StreamPi.Server.Main;
-import com.StreamPi.Server.Connection.ServerListener;
-import com.StreamPi.Server.Window.ExceptionAndAlertHandler;
-import com.StreamPi.Util.FormHelper.SpaceFiller;
-import com.StreamPi.Util.FormHelper.SpaceFiller.FillerType;
-
-import javafx.event.ActionEvent;
-import javafx.geometry.Insets;
-import javafx.geometry.Pos;
-import javafx.scene.control.Button;
-import javafx.scene.control.Label;
-import javafx.scene.layout.HBox;
-import javafx.scene.layout.Pane;
-import javafx.scene.layout.Priority;
-import javafx.scene.layout.StackPane;
-import javafx.scene.layout.VBox;
-import javafx.scene.text.Font;
-
-public class FirstTimeUse extends VBox{
-
-
- public FirstTimeUse(ExceptionAndAlertHandler exceptionAndAlertHandler, ServerListener serverListener)
- {
- Font.loadFont(Main.class.getResourceAsStream("Roboto.ttf"), 13);
- getStylesheets().add(Main.class.getResource("style.css").toExternalForm());
-
- getStyleClass().add("first_time_use_pane");
-
- setSpacing(10.0);
- setPadding(new Insets(5));
-
- headingLabel = new Label();
- headingLabel.getStyleClass().add("first_time_use_pane_heading_label");
-
- StackPane stackPane = new StackPane();
- stackPane.getStyleClass().add("first_time_use_pane_stackpane");
-
- VBox.setVgrow(stackPane, Priority.ALWAYS);
-
- welcomePane = new WelcomePane();
- licensePane = new LicensePane();
- finalConfigPane = new FinalConfigPane(exceptionAndAlertHandler, serverListener);
-
- stackPane.getChildren().addAll(
- welcomePane,
- licensePane,
- finalConfigPane
- );
-
-
- nextButton = new Button("Next");
- nextButton.setOnAction(event-> onNextButtonClicked());
-
- previousButton = new Button("Previous");
- previousButton.setOnAction(event-> onPreviousButtonClicked());
-
-
- HBox buttonBar = new HBox(previousButton, new SpaceFiller(FillerType.HBox), nextButton);
- buttonBar.setSpacing(10.0);
-
- getChildren().addAll(headingLabel, stackPane, buttonBar);
-
- setWindow(WindowName.WELCOME);
- }
-
- private Label headingLabel;
- private Button nextButton;
- private Button previousButton;
- private WelcomePane welcomePane;
- private LicensePane licensePane;
- private FinalConfigPane finalConfigPane;
-
- private WindowName windowName;
-
- private void onNextButtonClicked()
- {
- if(windowName == WindowName.WELCOME)
- {
- setWindow(WindowName.LICENSE);
- }
- else if(windowName == WindowName.LICENSE)
- {
- setWindow(WindowName.FINAL);
- }
- }
-
- private void onPreviousButtonClicked()
- {
- if(windowName == WindowName.FINAL)
- {
- setWindow(WindowName.LICENSE);
- }
- else if(windowName == WindowName.LICENSE)
- {
- setWindow(WindowName.WELCOME);
- }
- }
-
- private void setWindow(WindowName windowName)
- {
- if (windowName == WindowName.WELCOME)
- {
- this.windowName = WindowName.WELCOME;
- welcomePane.toFront();
- welcomePane.setVisible(true);
- licensePane.setVisible(false);
- finalConfigPane.setVisible(false);
-
- headingLabel.setText("");
-
- nextButton.setDisable(false);
- previousButton.setDisable(true);
- }
- else if (windowName == WindowName.LICENSE)
- {
- this.windowName = WindowName.LICENSE;
- licensePane.toFront();
- welcomePane.setVisible(false);
- licensePane.setVisible(true);
- finalConfigPane.setVisible(false);
-
- headingLabel.setText("License Agreement");
-
- nextButton.setDisable(false);
- previousButton.setDisable(false);
- }
- else if (windowName == WindowName.FINAL)
- {
- this.windowName = WindowName.FINAL;
- finalConfigPane.toFront();
- welcomePane.setVisible(false);
- licensePane.setVisible(false);
- finalConfigPane.setVisible(true);
-
- headingLabel.setText("Finishing up ...");
-
- nextButton.setDisable(true);
- previousButton.setDisable(false);
- }
- }
-
-
-
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/FirstTimeUse/LicensePane.java'
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.StreamPi.Server.Window.FirstTimeUse;
-
-import com.StreamPi.Server.Info.License;
-
-import javafx.scene.control.Label;
-import javafx.scene.control.TextArea;
-import javafx.scene.layout.Priority;
-import javafx.scene.layout.VBox;
-
-public class LicensePane extends VBox {
- public LicensePane()
- {
- getStyleClass().add("first_time_use_pane_license");
-
- Label label = new Label("By Clicking on 'Next', you agree with the license of StreamPi, and the license(s) of the library(s) used/included with this software.");
- label.prefWidthProperty().bind(widthProperty());
- label.setWrapText(true);
-
- TextArea licenseTextArea = new TextArea(License.getLicense());
- licenseTextArea.setWrapText(false);
- licenseTextArea.setEditable(false);
-
- licenseTextArea.prefWidthProperty().bind(widthProperty());
- VBox.setVgrow(licenseTextArea, Priority.ALWAYS);
-
- getChildren().addAll(label, licenseTextArea);
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/FirstTimeUse/WelcomePane.java'
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.StreamPi.Server.Window.FirstTimeUse;
-
-import javafx.geometry.Pos;
-import javafx.scene.control.Label;
-import javafx.scene.layout.VBox;
-
-public class WelcomePane extends VBox{
- public WelcomePane()
- {
- getStyleClass().add("first_time_use_pane_welcome");
-
- Label welcomeLabel = new Label("Welcome!");
- welcomeLabel.getStyleClass().add("first_time_use_welcome_pane_welcome_label");
-
- Label nextToContinue = new Label("Click on Next to continue with the setup.");
- nextToContinue.getStyleClass().add("first_time_use_welcome_pane_next_to_continue_label");
-
-
- setAlignment(Pos.CENTER);
- setSpacing(5.0);
- getChildren().addAll(welcomeLabel, nextToContinue);
-
- setVisible(false);
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/FirstTimeUse/WindowName.java'
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.StreamPi.Server.Window.FirstTimeUse;
-
-public enum WindowName {
- WELCOME, LICENSE, FINAL
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/Settings/About.java'
+++ /dev/null
@@ -1,111 +0,0 @@
-package com.StreamPi.Server.Window.Settings;
-
-import com.StreamPi.ActionAPI.ActionAPI;
-import com.StreamPi.Server.Info.License;
-import com.StreamPi.Server.Info.ServerInfo;
-import com.StreamPi.Server.Main;
-import com.StreamPi.Util.Platform.Platform;
-import com.StreamPi.Util.Platform.ReleaseStatus;
-import javafx.application.HostServices;
-import javafx.geometry.Insets;
-import javafx.geometry.Pos;
-import javafx.scene.control.Hyperlink;
-import javafx.scene.control.Label;
-import javafx.scene.control.TextArea;
-import javafx.scene.image.Image;
-import javafx.scene.image.ImageView;
-import javafx.scene.layout.HBox;
-import javafx.scene.layout.Priority;
-import javafx.scene.layout.Region;
-import javafx.scene.layout.VBox;
-
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.net.URL;
-
-public class About extends VBox{
-
- private HostServices hostServices;
-
- public About(HostServices hostServices)
- {
- getStyleClass().add("about");
- this.hostServices = hostServices;
-
- setAlignment(Pos.TOP_CENTER);
-
- Image appIcon = new Image(Main.class.getResourceAsStream("app_icon.png"));
- ImageView appIconImageView = new ImageView(appIcon);
- appIconImageView.setFitHeight(196);
- appIconImageView.setFitWidth(182);
-
- Label licenseLabel = new Label("License");
- licenseLabel.getStyleClass().add("settings_about_license_label");
-
- VBox.setMargin(licenseLabel, new Insets(20, 0 , 10 ,0));
-
- TextArea licenseTextArea = new TextArea(License.getLicense());
- licenseTextArea.setWrapText(false);
- licenseTextArea.setEditable(false);
- licenseTextArea.setMaxWidth(550);
-
- VBox.setVgrow(licenseTextArea, Priority.ALWAYS);
-
- HBox links = new HBox();
-
- Hyperlink github = new Hyperlink("GitHub");
- github.setOnAction(event -> {
- openWebpage("https://github.com/Stream-Pi");
- });
-
- Hyperlink discord = new Hyperlink("Discord");
- discord.setOnAction(event -> {
- openWebpage("https://discord.gg/BExqGmk");
- });
-
- Hyperlink website = new Hyperlink("Website");
- website.setOnAction(event -> {
- openWebpage("https://stream-pi.com");
- });
-
- Hyperlink twitter = new Hyperlink("Twitter");
- twitter.setOnAction(event -> {
- openWebpage("https://twitter.com/Stream_Pi");
- });
-
- Hyperlink matrix = new Hyperlink("Matrix");
- matrix.setOnAction(event -> {
- openWebpage("https://matrix.to/#/#stream-pi_general:matrix.org");
- });
-
-
- links.setSpacing(30);
- links.setAlignment(Pos.CENTER);
- links.getChildren().addAll(github, matrix, discord, website, twitter);
-
- Hyperlink donateButton = new Hyperlink("DONATE");
- donateButton.setOnAction(event -> {
- openWebpage("https://www.patreon.com/streampi");
- });
- donateButton.getStyleClass().add("settings_about_donate_hyperlink");
-
-
- ServerInfo serverInfo = ServerInfo.getInstance();
-
- Label versionText = new Label(serverInfo.getVersion().getText() + " - "+ serverInfo.getPlatformType().getUIName() + " - "+ serverInfo.getReleaseStatus().getUIName());
- Label commStandardLabel = new Label("Comm Standard "+serverInfo.getCommStandardVersion().getText());
- Label minThemeAPILabel = new Label("Min ThemeAPI "+serverInfo.getMinThemeSupportVersion().getText());
- Label minActionAPILabel = new Label("Min ActionAPI "+serverInfo.getMinPluginSupportVersion().getText());
-
-
- Label currentActionAPILabel = new Label("ActionAPI "+ ActionAPI.API_VERSION.getText());
-
- setSpacing(3);
-
- getChildren().addAll(appIconImageView, licenseLabel, licenseTextArea, links, donateButton, versionText, commStandardLabel, minThemeAPILabel, minActionAPILabel, currentActionAPILabel);
- }
-
- public void openWebpage(String url) {
- hostServices.showDocument(url);
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/Settings/ClientsSettings.java'
+++ /dev/null
@@ -1,713 +0,0 @@
-package com.StreamPi.Server.Window.Settings;
-
-import com.StreamPi.Server.Client.Client;
-import com.StreamPi.Server.Client.ClientProfile;
-import com.StreamPi.Server.Client.ClientTheme;
-import com.StreamPi.Server.Connection.ClientConnection;
-import com.StreamPi.Server.Connection.ClientConnections;
-import com.StreamPi.Server.Connection.ServerListener;
-import com.StreamPi.Server.Window.ExceptionAndAlertHandler;
-import com.StreamPi.Util.Exception.MinorException;
-import com.StreamPi.Util.Exception.SevereException;
-import com.StreamPi.Util.FormHelper.HBoxInputBox;
-import com.StreamPi.Util.FormHelper.SpaceFiller;
-import com.StreamPi.Util.Platform.ReleaseStatus;
-import javafx.application.Platform;
-import javafx.collections.FXCollections;
-import javafx.concurrent.Task;
-import javafx.geometry.Insets;
-import javafx.geometry.Pos;
-import javafx.scene.CacheHint;
-import javafx.scene.Node;
-import javafx.scene.control.*;
-import javafx.scene.layout.HBox;
-import javafx.scene.layout.Priority;
-import javafx.scene.layout.VBox;
-import javafx.util.Callback;
-import org.w3c.dom.Text;
-
-import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Logger;
-
-public class ClientsSettings extends VBox {
- private VBox clientsSettingsVBox;
- private Button saveButton;
-
- private ServerListener serverListener;
-
- private Logger logger;
-
- private ExceptionAndAlertHandler exceptionAndAlertHandler;
-
- public ClientsSettings(ExceptionAndAlertHandler exceptionAndAlertHandler, ServerListener serverListener)
- {
- getStyleClass().add("clients_settings");
- this.serverListener = serverListener;
- this.exceptionAndAlertHandler = exceptionAndAlertHandler;
-
- clientSettingsVBoxArrayList = new ArrayList<>();
-
- setPadding(new Insets(10.0));
-
- logger = Logger.getLogger(ClientsSettings.class.getName());
-
- clientsSettingsVBox = new VBox();
- clientsSettingsVBox.setSpacing(20.0);
- clientsSettingsVBox.setAlignment(Pos.TOP_CENTER);
-
- setAlignment(Pos.TOP_CENTER);
-
- ScrollPane scrollPane = new ScrollPane();
- scrollPane.getStyleClass().add("clients_settings_scroll_pane");
- scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
- VBox.setVgrow(scrollPane, Priority.ALWAYS);
- scrollPane.maxWidthProperty().bind(widthProperty().multiply(0.8));
-
- clientsSettingsVBox.prefWidthProperty().bind(scrollPane.widthProperty().subtract(25));
- scrollPane.setContent(clientsSettingsVBox);
-
- saveButton = new Button("Save");
- saveButton.setOnAction(event -> onSaveButtonClicked());
-
- HBox hBox = new HBox(saveButton);
- hBox.setAlignment(Pos.CENTER_RIGHT);
-
- getChildren().addAll(scrollPane, hBox);
-
- setCache(true);
- setCacheHint(CacheHint.SPEED);
- }
-
- public void onSaveButtonClicked()
- {
- new Thread(new Task<Void>() {
- @Override
- protected Void call()
- {
- try
- {
- Platform.runLater(()->saveButton.setDisable(true));
- StringBuilder finalErrors = new StringBuilder();
-
- for(ClientSettingsVBox clientSettingsVBox : clientSettingsVBoxArrayList)
- {
- StringBuilder errors = new StringBuilder();
-
- if(clientSettingsVBox.getNickname().isBlank())
- errors.append(" Cannot have blank nickname. \n");
-
- try {
- Double.parseDouble(clientSettingsVBox.getStartupWindowHeight());
- }
- catch (NumberFormatException e)
- {
- errors.append(" Must have integer display height. \n");
- }
-
- try {
- Double.parseDouble(clientSettingsVBox.getStartupWindowWidth());
- }
- catch (NumberFormatException e)
- {
- errors.append(" Must have integer display width. \n");
- }
-
- for(ClientProfileVBox clientProfileVBox : clientSettingsVBox.getClientProfileVBoxes())
- {
- StringBuilder errors2 = new StringBuilder();
-
- if(clientProfileVBox.getName().isBlank())
- errors2.append(" cannot have blank nickname. \n");
-
- try {
- Integer.parseInt(clientProfileVBox.getActionSize());
- }
- catch (NumberFormatException e)
- {
- errors2.append(" Must have integer Action Size. \n");
- }
-
-
- try {
- Integer.parseInt(clientProfileVBox.getActionGap());
- }
- catch (NumberFormatException e)
- {
- errors2.append(" Must have integer Action Gap. \n");
- }
-
-
- try {
- int rows = Integer.parseInt(clientProfileVBox.getRows());
-
- int actionsSize = Integer.parseInt(clientProfileVBox.getActionSize());
- double startupWidth = Double.parseDouble(clientSettingsVBox.getStartupWindowWidth());
-
-
- if((rows*actionsSize) > (startupWidth - 25) && clientSettingsVBox.getPlatform()!= com.StreamPi.Util.Platform.Platform.ANDROID)
- {
- errors2.append(" Rows out of bounds of screen size. \n"+startupWidth);
- }
- }
- catch (NumberFormatException e)
- {
- errors2.append(" Must have integer Rows. \n");
- }
-
-
- try {
- int cols = Integer.parseInt(clientProfileVBox.getCols());
-
- int actionsSize = Integer.parseInt(clientProfileVBox.getActionSize());
- double startupHeight = Double.parseDouble(clientSettingsVBox.getStartupWindowHeight());
-
- if((cols*actionsSize) > (startupHeight - 25) && clientSettingsVBox.getPlatform()!= com.StreamPi.Util.Platform.Platform.ANDROID)
- {
- errors2.append(" Cols out of bounds of screen size. \n"+startupHeight);
- }
- }
- catch (NumberFormatException e)
- {
- errors2.append(" Must have integer Columns. \n");
- }
-
-
- if(!errors2.toString().isEmpty())
- {
- errors.append(" ")
- .append(clientProfileVBox.getRealName())
- .append("\n")
- .append(errors2.toString())
- .append("\n");
- }
- }
-
-
- if(!errors.toString().isEmpty())
- {
- finalErrors.append("* ")
- .append(clientSettingsVBox.getRealNickName())
- .append("\n")
- .append(errors.toString())
- .append("\n");
- }
-
-
-
- }
-
- if(!finalErrors.toString().isEmpty())
- throw new MinorException("You made form mistakes",
- "Please fix the following issues : \n"+finalErrors.toString());
-
-
-
- //save details and values
- for(ClientSettingsVBox clientSettingsVBox : clientSettingsVBoxArrayList)
- {
- clientSettingsVBox.saveClientAndProfileDetails();
- }
-
- loadData();
- serverListener.clearTemp();
- }
- catch (MinorException e)
- {
- e.printStackTrace();
- exceptionAndAlertHandler.handleMinorException(e);
- }
- catch (SevereException e)
- {
- e.printStackTrace();
- exceptionAndAlertHandler.handleSevereException(e);
- }
- catch (CloneNotSupportedException e)
- {
- e.printStackTrace();
- exceptionAndAlertHandler.handleSevereException(new SevereException(
- e.getMessage()
- ));
- }
- finally
- {
- Platform.runLater(()->saveButton.setDisable(false));
- }
- return null;
- }
- }).start();
- }
-
- private ArrayList<ClientSettingsVBox> clientSettingsVBoxArrayList;
-
- public void loadData()
- {
- logger.info("Loading client data into ClientsSettings ...");
-
- Platform.runLater(()-> clientsSettingsVBox.getChildren().clear());
- clientSettingsVBoxArrayList.clear();
-
- List<ClientConnection> clientConnections = ClientConnections.getInstance().getConnections();
-
- if(clientConnections.size() == 0)
- {
- Platform.runLater(()->{
- clientsSettingsVBox.getChildren().add(new Label("No Clients Connected."));
- saveButton.setVisible(false);
- });
- }
- else
- {
- Platform.runLater(()->saveButton.setVisible(true));
- for (ClientConnection clientConnection : clientConnections) {
- ClientSettingsVBox clientSettingsVBox = new ClientSettingsVBox(clientConnection);
-
- clientSettingsVBoxArrayList.add(clientSettingsVBox);
- Platform.runLater(()->clientsSettingsVBox.getChildren().add(clientSettingsVBox));
- }
- }
-
- logger.info("... Done!");
- }
-
- public class ClientSettingsVBox extends VBox
- {
- private ComboBox<ClientProfile> profilesComboBox;
-
- private ComboBox<ClientTheme> themesComboBox;
-
- private TextField startupWindowHeightTextField;
-
- public String getStartupWindowHeight() {
- return startupWindowHeightTextField.getText();
- }
-
- private TextField startupWindowWidthTextField;
-
- public String getStartupWindowWidth() {
- return startupWindowWidthTextField.getText();
- }
-
- private TextField nicknameTextField;
-
- public String getNickname() {
- return nicknameTextField.getText();
- }
-
- private Label nickNameLabel;
-
- private Label versionLabel;
-
- public String getRealNickName()
- {
- return nickNameLabel.getText();
- }
-
- private com.StreamPi.Util.Platform.Platform platform;
-
- public com.StreamPi.Util.Platform.Platform getPlatform() {
- return platform;
- }
-
- private Label socketConnectionLabel;
-
- private ClientConnection connection;
-
- private Accordion profilesAccordion;
-
- private ArrayList<ClientProfileVBox> clientProfileVBoxes;
-
- private Label platformLabel;
-
- private HBoxInputBox startupWindowHeightInputBox, startupWindowWidthInputBox;
-
- public ArrayList<ClientProfileVBox> getClientProfileVBoxes() {
- return clientProfileVBoxes;
- }
-
- public ClientSettingsVBox(ClientConnection connection)
- {
- this.connection = connection;
- this.platform = connection.getClient().getPlatform();
-
- clientProfileVBoxes = new ArrayList<>();
-
- initUI();
- loadValues();
- }
-
- public ClientConnection getConnection()
- {
- return connection;
- }
-
- public void saveClientAndProfileDetails() throws SevereException, CloneNotSupportedException, MinorException {
- System.out.println("IIN");
- getConnection().saveClientDetails(
- nicknameTextField.getText(),
- startupWindowWidthTextField.getText(),
- startupWindowHeightTextField.getText(),
- profilesComboBox.getSelectionModel().getSelectedItem().getID(),
- themesComboBox.getSelectionModel().getSelectedItem().getThemeFullName()
- );
-
- System.out.println("OUT");
-
- logger.info("Profiles : ");
- for(ClientProfileVBox clientProfileVBox : clientProfileVBoxes)
- {
- logger.info("Name : "+clientProfileVBox.getClientProfile().getName());
- getConnection().saveProfileDetails(clientProfileVBox.getClientProfile());
- }
-
-
- //remove deleted client profiles
- for(ClientProfile clientProfile : connection.getClient().getAllClientProfiles())
- {
- boolean found = false;
- for(ClientProfileVBox clientProfileVBox : clientProfileVBoxes)
- {
- if(clientProfileVBox.getClientProfile().getID().equals(clientProfile.getID()))
- {
- found = true;
- break;
- }
- }
-
- if(!found)
- {
- connection.getClient().removeProfileFromID(clientProfile.getID());
- connection.deleteProfile(clientProfile.getID());
- }
- }
-
-
- }
-
- public void initUI()
- {
- profilesComboBox = new ComboBox<>();
- Callback<ListView<ClientProfile>, ListCell<ClientProfile>> profilesComboBoxFactory = new Callback<>() {
- @Override
- public ListCell<ClientProfile> call(ListView<ClientProfile> clientConnectionListView) {
-
- return new ListCell<>() {
- @Override
- protected void updateItem(ClientProfile clientProfile, boolean b) {
- super.updateItem(clientProfile, b);
-
- if(clientProfile == null)
- {
- setText(null);
- }
- else
- {
- setText(clientProfile.getName());
- }
- }
- };
- }
- };
- profilesComboBox.setCellFactory(profilesComboBoxFactory);
- profilesComboBox.setButtonCell(profilesComboBoxFactory.call(null));
-
- themesComboBox = new ComboBox<>();
- Callback<ListView<ClientTheme>, ListCell<ClientTheme>> themesComboBoxFactory = new Callback<>() {
- @Override
- public ListCell<ClientTheme> call(ListView<ClientTheme> clientConnectionListView) {
-
- return new ListCell<>() {
- @Override
- protected void updateItem(ClientTheme clientTheme, boolean b) {
- super.updateItem(clientTheme, b);
-
- if(clientTheme == null)
- {
- setText(null);
- }
- else
- {
- setText(clientTheme.getShortName());
- }
- }
- };
- }
- };
- themesComboBox.setCellFactory(themesComboBoxFactory);
- themesComboBox.setButtonCell(themesComboBoxFactory.call(null));
-
- startupWindowHeightTextField = new TextField();
- startupWindowWidthTextField = new TextField();
-
- platformLabel = new Label();
- platformLabel.getStyleClass().add("settings_client_platform_label");
-
- socketConnectionLabel = new Label();
- socketConnectionLabel.getStyleClass().add("settings_client_socket_connection_label");
-
- nicknameTextField = new TextField();
-
- nickNameLabel = new Label();
- nickNameLabel.getStyleClass().add("settings_client_nick_name_label");
-
- versionLabel = new Label();
- versionLabel.getStyleClass().add("settings_client_version_label");
-
- profilesAccordion = new Accordion();
- VBox.setMargin(profilesAccordion, new Insets(0,0,20,0));
-
-
- Button addNewProfileButton = new Button("Add new Profile");
- addNewProfileButton.setOnAction(event -> onNewProfileButtonClicked());
-
- setSpacing(10.0);
-
- getStyleClass().add("settings_clients_each_client");
-
-
- startupWindowHeightInputBox = new HBoxInputBox("Startup Window Height", startupWindowHeightTextField);
- startupWindowHeightInputBox.managedProperty().bind(startupWindowHeightInputBox.visibleProperty());
-
- startupWindowWidthInputBox = new HBoxInputBox("Startup Window Width", startupWindowWidthTextField);
- startupWindowWidthInputBox.managedProperty().bind(startupWindowWidthInputBox.visibleProperty());
-
-
- this.getChildren().addAll(
- nickNameLabel,
- socketConnectionLabel,
- platformLabel,
- versionLabel,
- new HBoxInputBox("Nickname",nicknameTextField),
- new HBox(
- new Label("Theme"),
- new SpaceFiller(SpaceFiller.FillerType.HBox),
- themesComboBox
- ),
-
- startupWindowHeightInputBox,
-
- startupWindowWidthInputBox,
-
- new HBox(new Label("Startup Profile"),
- new SpaceFiller(SpaceFiller.FillerType.HBox),
- profilesComboBox),
-
- addNewProfileButton,
-
- profilesAccordion);
- }
-
- public void loadValues()
- {
- Client client = connection.getClient();
-
- profilesComboBox.setItems(FXCollections.observableList(client.getAllClientProfiles()));
- profilesComboBox.getSelectionModel().select(
- client.getProfileByID(client.getDefaultProfileID())
- );
-
-
- themesComboBox.setItems(FXCollections.observableList(client.getThemes()));
- themesComboBox.getSelectionModel().select(
- client.getThemeByFullName(
- client.getDefaultThemeFullName()
- )
- );
-
- nicknameTextField.setText(client.getNickName());
-
- if(client.getPlatform() == com.StreamPi.Util.Platform.Platform.ANDROID)
- {
- startupWindowHeightInputBox.setVisible(false);
- startupWindowWidthInputBox.setVisible(false);
- }
-
- platformLabel.setText("Platform : "+client.getPlatform().getUIName());
-
- startupWindowWidthTextField.setText(client.getStartupDisplayWidth()+"");
- startupWindowHeightTextField.setText(client.getStartupDisplayHeight()+"");
-
- socketConnectionLabel.setText(client.getRemoteSocketAddress().toString().substring(1)); //substring removes the `/`
-
- nickNameLabel.setText(client.getNickName());
-
- versionLabel.setText(client.getReleaseStatus().getUIName()+" "+client.getVersion().getText());
-
- //add profiles
- for(ClientProfile clientProfile : client.getAllClientProfiles())
- {
- TitledPane titledPane = new TitledPane();
- titledPane.setText(clientProfile.getName());
-
- ClientProfileVBox clientProfileVBox = new ClientProfileVBox(clientProfile);
-
- clientProfileVBox.getRemoveButton().setOnAction(event -> onProfileDeleteButtonClicked(clientProfileVBox, titledPane));
-
- titledPane.setContent(clientProfileVBox);
-
- clientProfileVBoxes.add(clientProfileVBox);
-
- profilesAccordion.getPanes().add(titledPane);
- }
- }
-
- public void onNewProfileButtonClicked()
- {
- ClientProfile clientProfile = new ClientProfile(
- "Untitled Profile",
- 3,
- 3,
- 100,
- 5
- );
-
-
- ClientProfileVBox clientProfileVBox = new ClientProfileVBox(clientProfile);
- TitledPane titledPane = new TitledPane();
- titledPane.setContent(clientProfileVBox);
- titledPane.setText(clientProfile.getName());
-
- clientProfileVBox.getRemoveButton().setOnAction(event -> onProfileDeleteButtonClicked(clientProfileVBox, titledPane));
-
- clientProfileVBoxes.add(clientProfileVBox);
-
- profilesAccordion.getPanes().add(titledPane);
- }
-
- public void onProfileDeleteButtonClicked(ClientProfileVBox clientProfileVBox, TitledPane titledPane)
- {
- if(clientProfileVBoxes.size() == 1)
- {
- exceptionAndAlertHandler.handleMinorException(new MinorException("Only one",
- "You cannot delete all profiles"));
- }
- else
- {
- if(profilesComboBox.getSelectionModel().getSelectedItem().getID().equals(clientProfileVBox.getClientProfile().getID()))
- {
- exceptionAndAlertHandler.handleMinorException(new MinorException("Default",
- "You cannot delete default profile. Change to another one to delete this."));
- }
- else
- {
- clientProfileVBoxes.remove(clientProfileVBox);
- profilesComboBox.getItems().remove(clientProfileVBox.getClientProfile());
-
- profilesAccordion.getPanes().remove(titledPane);
- }
- }
- }
- }
-
- public class ClientProfileVBox extends VBox
- {
- private TextField nameTextField;
-
- public String getName()
- {
- return nameTextField.getText();
- }
-
- private TextField rowsTextField;
-
- public String getRows()
- {
- return rowsTextField.getText();
- }
-
- private TextField colsTextField;
-
- public String getCols()
- {
- return colsTextField.getText();
- }
-
- private TextField actionSizeTextField;
-
- public String getActionSize()
- {
- return actionSizeTextField.getText();
- }
-
- private TextField actionGapTextField;
-
- public String getActionGap()
- {
- return actionGapTextField.getText();
- }
-
- private Button removeButton;
-
- private ClientProfile clientProfile;
-
- public String getRealName()
- {
- return clientProfile.getName();
- }
-
- public ClientProfileVBox(ClientProfile clientProfile)
- {
- this.clientProfile = clientProfile;
-
- initUI();
- loadValues(clientProfile);
- }
-
- public void initUI()
- {
- setPadding(new Insets(5.0));
- setSpacing(10.0);
-
- nameTextField = new TextField();
- rowsTextField = new TextField();
- colsTextField = new TextField();
- actionSizeTextField = new TextField();
- actionGapTextField = new TextField();
-
- removeButton = new Button("Remove");
-
- HBox hBox = new HBox(removeButton);
- hBox.setAlignment(Pos.CENTER_RIGHT);
-
-
- getChildren().addAll(
- new HBoxInputBox("Name ", nameTextField),
- new HBoxInputBox("Columns", rowsTextField),
- new HBoxInputBox("Rows", colsTextField),
- new HBoxInputBox("Action Size", actionSizeTextField),
- new HBoxInputBox("Action Gap", actionGapTextField),
- hBox
- );
- }
-
- public Button getRemoveButton()
- {
- return removeButton;
- }
-
- public void loadValues(ClientProfile clientProfile)
- {
- nameTextField.setText(clientProfile.getName());
-
- rowsTextField.setText(clientProfile.getRows()+"");
- colsTextField.setText(clientProfile.getCols()+"");
-
- actionSizeTextField.setText(clientProfile.getActionSize()+"");
- actionGapTextField.setText(clientProfile.getActionGap()+"");
- }
-
- public ClientProfile getClientProfile()
- {
- clientProfile.setActionGap(Integer.parseInt(actionGapTextField.getText()));
- clientProfile.setActionSize(Integer.parseInt(actionSizeTextField.getText()));
- clientProfile.setRows(Integer.parseInt(rowsTextField.getText()));
- clientProfile.setCols(Integer.parseInt(colsTextField.getText()));
- clientProfile.setName(nameTextField.getText());
-
- return clientProfile;
- }
- }
-
-
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/Settings/GeneralSettings.java'
+++ /dev/null
@@ -1,492 +0,0 @@
-package com.StreamPi.Server.Window.Settings;
-
-import com.StreamPi.Server.Connection.ServerListener;
-import com.StreamPi.Server.IO.Config;
-import com.StreamPi.Server.Controller.Controller;
-import com.StreamPi.Server.Window.ExceptionAndAlertHandler;
-import com.StreamPi.ThemeAPI.Theme;
-import com.StreamPi.Util.Alert.StreamPiAlert;
-import com.StreamPi.Util.Alert.StreamPiAlertType;
-import com.StreamPi.Util.Exception.MinorException;
-import com.StreamPi.Util.Exception.SevereException;
-import com.StreamPi.Util.StartAtBoot.SoftwareType;
-import com.StreamPi.Util.StartAtBoot.StartAtBoot;
-import com.StreamPi.Util.Version.Version;
-import com.StreamPi.Server.Info.ServerInfo;
-
-import javafx.application.HostServices;
-import javafx.application.Platform;
-import javafx.concurrent.Task;
-import javafx.geometry.Insets;
-import javafx.geometry.Pos;
-import javafx.scene.control.*;
-import javafx.scene.control.Button;
-import javafx.scene.control.Label;
-import javafx.scene.control.ScrollPane;
-import javafx.scene.control.TextField;
-import javafx.scene.layout.*;
-import javafx.scene.paint.Paint;
-import javafx.stage.DirectoryChooser;
-import javafx.stage.Stage;
-import org.json.JSONObject;
-import org.kordamp.ikonli.javafx.FontIcon;
-import org.w3c.dom.Text;
-import java.awt.SystemTray;
-import java.awt.Toolkit;
-import java.awt.TrayIcon;
-import java.awt.PopupMenu;
-import java.awt.MenuItem;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.logging.Logger;
-
-public class GeneralSettings extends ScrollPane {
-
- private final TextField serverNameTextField;
- private final TextField portTextField;
- private final TextField pluginsPathTextField;
- private final TextField themesPathTextField;
- private final TextField actionGridPaneActionBoxSize;
- private final TextField actionGridPaneActionBoxGap;
- private final ToggleButton startOnBootToggleButton;
- private final ToggleButton closeOnXToggleButton;
- private final Button saveButton;
- private final Button checkForUpdatesButton;
-
-
- private Logger logger;
-
- private ExceptionAndAlertHandler exceptionAndAlertHandler;
-
- private ServerListener serverListener;
-
- private HostServices hostServices;
-
- public GeneralSettings(ExceptionAndAlertHandler exceptionAndAlertHandler, ServerListener serverListener, HostServices hostServices)
- {
- this.hostServices = hostServices;
-
- getStyleClass().add("general_settings_scroll_pane");
-
-
- this.exceptionAndAlertHandler = exceptionAndAlertHandler;
- this.serverListener = serverListener;
-
- logger = Logger.getLogger(GeneralSettings.class.getName());
-
- setHbarPolicy(ScrollBarPolicy.NEVER);
-
- serverNameTextField = new TextField();
-
- portTextField = new TextField();
-
- pluginsPathTextField = new TextField();
-
- themesPathTextField = new TextField();
-
- actionGridPaneActionBoxSize = new TextField();
- actionGridPaneActionBoxGap = new TextField();
-
- startOnBootToggleButton = new ToggleButton("Start on Boot");
- closeOnXToggleButton = new ToggleButton("Quit On Window Close");
-
- checkForUpdatesButton = new Button("Check for updates");
- checkForUpdatesButton.setOnAction(event->checkForUpdates());
-
-
- VBox vBox = new VBox();
- vBox.prefWidthProperty().bind(widthProperty());
- vBox.setAlignment(Pos.CENTER);
- vBox.setSpacing(5);
-
- vBox.getChildren().addAll(
- getUIInputBox("Server Name", serverNameTextField),
- getUIInputBox("Port", portTextField),
- getUIInputBox("Action Grid Pane Action Box Size", actionGridPaneActionBoxSize),
- getUIInputBox("Action Grid Pane Action Box Gap", actionGridPaneActionBoxGap),
- getUIInputBoxWithDirectoryChooser("Plugins Path", pluginsPathTextField),
- getUIInputBoxWithDirectoryChooser("Themes Path", themesPathTextField)
- );
-
- serverNameTextField.setPrefWidth(200);
-
- HBox toggleButtons = new HBox(closeOnXToggleButton, startOnBootToggleButton);
- toggleButtons.setSpacing(10.0);
- VBox.setMargin(toggleButtons, new Insets(30, 0 , 0,0));
- toggleButtons.setAlignment(Pos.CENTER);
-
- saveButton = new Button("Save");
- saveButton.setOnAction(event->save());
-
- vBox.getChildren().addAll(toggleButtons, checkForUpdatesButton, saveButton);
-
- vBox.setPadding(new Insets(10));
-
-
- vBox.getStyleClass().add("general_settings");
- setContent(vBox);
- }
-
- private HBox getUIInputBoxWithDirectoryChooser(String labelText, TextField textField)
- {
- HBox hBox = getUIInputBox(labelText, textField);
- hBox.setSpacing(5.0);
-
- TextField tf = (TextField) hBox.getChildren().get(2);
- tf.setPrefWidth(300);
- tf.setDisable(true);
-
-
- Button button = new Button();
- FontIcon fontIcon = new FontIcon("far-folder");
- button.setGraphic(fontIcon);
-
- button.setOnAction(event -> {
- DirectoryChooser directoryChooser = new DirectoryChooser();
-
-
- try {
- File selectedDirectory = directoryChooser.showDialog(getScene().getWindow());
-
- textField.setText(selectedDirectory.getAbsolutePath());
- }
- catch (NullPointerException e)
- {
- logger.info("No folder selected");
- }
- });
-
- hBox.getChildren().add(button);
-
-
- return hBox;
- }
-
- private HBox getUIInputBox(String labelText, TextField textField)
- {
- textField.setPrefWidth(100);
-
- Label label = new Label(labelText);
- Region region = new Region();
- HBox.setHgrow(region, Priority.ALWAYS);
-
-
- return new HBox(label, region, textField);
- }
-
-
-
- public void loadDataFromConfig() throws SevereException {
- Config config = Config.getInstance();
-
- Platform.runLater(()->
- {
- serverNameTextField.setText(config.getServerName());
- portTextField.setText(config.getPort()+"");
- pluginsPathTextField.setText(config.getPluginsPath());
- themesPathTextField.setText(config.getThemesPath());
- actionGridPaneActionBoxSize.setText(config.getActionGridActionSize()+"");
- actionGridPaneActionBoxGap.setText(config.getActionGridActionGap()+"");
-
- closeOnXToggleButton.setSelected(config.getCloseOnX());
- startOnBootToggleButton.setSelected(config.getStartOnBoot());
- });
- }
-
- public void save()
- {
- new Thread(new Task<Void>() {
- @Override
- protected Void call()
- {
- try {
- boolean toBeReloaded = false;
- boolean dashToBeReRendered = false;
-
- Platform.runLater(()->{
- saveButton.setDisable(true);
-
- serverNameTextField.setDisable(true);
- portTextField.setDisable(true);
-
- closeOnXToggleButton.setDisable(true);
- startOnBootToggleButton.setDisable(true);
- });
-
- String serverNameStr = serverNameTextField.getText();
- String serverPortStr = portTextField.getText();
- String pluginsPathStr = pluginsPathTextField.getText();
- String themesPathStr = themesPathTextField.getText();
-
- String actionGridActionBoxSize = actionGridPaneActionBoxSize.getText();
- String actionGridActionBoxGap = actionGridPaneActionBoxGap.getText();
-
- boolean closeOnX = closeOnXToggleButton.isSelected();
- boolean startOnBoot = startOnBootToggleButton.isSelected();
-
- Config config = Config.getInstance();
-
- StringBuilder errors = new StringBuilder();
-
-
- if(serverNameStr.isBlank())
- {
- errors.append("* Server Name cannot be blank.\n");
- }
- else
- {
- if(!config.getServerName().equals(serverNameStr))
- {
- toBeReloaded = true;
- }
- }
-
-
- int serverPort=-1;
- try {
- serverPort = Integer.parseInt(serverPortStr);
-
- if (serverPort < 1024)
- errors.append("* Server Port must be more than 1024");
-
- if(config.getPort()!=serverPort)
- {
- toBeReloaded = true;
- }
- }
- catch (NumberFormatException e)
- {
- errors.append("* Server Port must be integer.\n");
- }
-
-
- int actionSize=-1;
- try {
- actionSize = Integer.parseInt(actionGridActionBoxSize);
-
- if(config.getActionGridActionSize() != actionSize)
- {
- dashToBeReRendered = true;
- }
- }
- catch (NumberFormatException e)
- {
- errors.append("* Action Size must be integer.\n");
- }
-
-
- int actionGap=-1;
- try {
- actionGap = Integer.parseInt(actionGridActionBoxGap);
-
- if(config.getActionGridActionGap() != actionGap)
- {
- dashToBeReRendered = true;
- }
- }
- catch (NumberFormatException e)
- {
- errors.append("* Action Gap must be integer.\n");
- }
-
- if(pluginsPathStr.isBlank())
- {
- errors.append("* Plugins Path must not be blank.\n");
- }
- else
- {
- if(!config.getPluginsPath().equals(pluginsPathStr))
- {
- toBeReloaded = true;
- }
- }
-
- if(themesPathStr.isBlank())
- {
- errors.append("* Themes Path must not be blank.\n");
- }
- else
- {
- if(!config.getThemesPath().equals(themesPathStr))
- {
- toBeReloaded = true;
- }
- }
-
- if(!errors.toString().isEmpty())
- {
- throw new MinorException("Settings", "Please rectify the following errors and try again :\n"+errors.toString());
- }
-
- if(config.getStartOnBoot() != startOnBoot)
- {
- if(ServerInfo.getInstance().getRunnerFileName() == null)
- {
- new StreamPiAlert("Uh Oh", "No Runner File Name Specified as startup arguments. Cant set run at boot.", StreamPiAlertType.ERROR).show();
- startOnBoot = false;
- }
- else
- {
- StartAtBoot startAtBoot = new StartAtBoot(SoftwareType.SERVER, ServerInfo.getInstance().getPlatformType());
- if(startOnBoot)
- {
- startAtBoot.create(new File(ServerInfo.getInstance().getRunnerFileName()));
- }
- else
- {
- boolean result = startAtBoot.delete();
- if(!result)
- new StreamPiAlert("Uh Oh!", "Unable to delete starter file", StreamPiAlertType.ERROR).show();
- }
- }
- }
-
- if(!closeOnX)
- {
- System.out.println("XYZ");
- if(!SystemTray.isSupported())
- {
- StreamPiAlert alert = new StreamPiAlert("Not Supported", "Tray System not supported on this platform ", StreamPiAlertType.ERROR);
- alert.show();
-
- closeOnX = true;
- }
- else
- {
- System.out.println("YES");
- }
- }
-
- config.setServerName(serverNameStr);
- config.setServerPort(serverPort);
- config.setActionGridGap(actionGap);
- config.setActionGridSize(actionSize);
- config.setPluginsPath(pluginsPathStr);
- config.setThemesPath(themesPathStr);
-
- config.setCloseOnX(closeOnX);
- config.setStartupOnBoot(startOnBoot);
-
- config.save();
-
-
- loadDataFromConfig();
-
- if(toBeReloaded)
- {
- new StreamPiAlert("Restart","Restart to see changes", StreamPiAlertType.INFORMATION).show();
- }
-
- if(dashToBeReRendered)
- {
- serverListener.clearTemp();
- }
- }
- catch (MinorException e)
- {
- exceptionAndAlertHandler.handleMinorException(e);
- }
- catch (SevereException e)
- {
- exceptionAndAlertHandler.handleSevereException(e);
- }
- finally {
- Platform.runLater(()->{
- saveButton.setDisable(false);
-
- serverNameTextField.setDisable(false);
- portTextField.setDisable(false);
-
- closeOnXToggleButton.setDisable(false);
- startOnBootToggleButton.setDisable(false);
- });
- }
- return null;
- }
- }).start();
- }
-
- public void checkForUpdates()
- {
- new Thread(new Task<Void>()
- {
- @Override
- protected Void call() throws Exception {
- try
- {
- Platform.runLater(()->checkForUpdatesButton.setDisable(true));
-
-
- String jsonRaw = readUrl("https://stream-pi.com/API/get_latest.php?TYPE=SERVER");
-
- System.out.println(jsonRaw);
-
- JSONObject jsonObject = new JSONObject(jsonRaw);
-
- String latestVersionRaw = jsonObject.getString("Version");
- String releasePage = jsonObject.getString("Release Page");
-
- Version latestVersion = new Version(latestVersionRaw);
- Version currentVersion = ServerInfo.getInstance().getVersion();
-
- if(latestVersion.isBiggerThan(currentVersion))
- {
- VBox vBox = new VBox();
-
- Hyperlink urlLabel = new Hyperlink(releasePage);
- urlLabel.setOnAction(event->hostServices.showDocument(releasePage));
-
- Label label = new Label(
- "New Version "+latestVersionRaw+" Available.\n" +
- "Current Version "+currentVersion.getText()+".\n"+
- "Changelog and install instructions are included in the release page.\n" +
- "It is recommended to update to ensure maximum stability and least bugs.");
- label.setWrapText(true);
-
- vBox.setSpacing(5);
- vBox.getChildren().addAll(
- urlLabel,
- label
- );
-
- new StreamPiAlert("New Update Available!", StreamPiAlertType.INFORMATION, vBox).show();;
- }
- else
- {
- new StreamPiAlert("Up to Date", "Server is upto date. ("+currentVersion.getText()+")", StreamPiAlertType.INFORMATION).show();;
- }
- }
- catch (Exception e)
- {
- e.printStackTrace();
- new StreamPiAlert("Uh Oh", "Update Check Failed. API Error/Network issue.", StreamPiAlertType.WARNING).show();;
- }
- finally
- {
- Platform.runLater(()->checkForUpdatesButton.setDisable(false));
- }
- return null;
- }
- }).start();;
- }
-
- private String readUrl(String urlString) throws Exception {
- BufferedReader reader = null;
- try {
- URL url = new URL(urlString);
- reader = new BufferedReader(new InputStreamReader(url.openStream()));
- StringBuffer buffer = new StringBuffer();
- int read;
- char[] chars = new char[1024];
- while ((read = reader.read(chars)) != -1)
- buffer.append(chars, 0, read);
-
- return buffer.toString();
- } finally {
- if (reader != null)
- reader.close();
- }
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/Settings/PluginsSettings.java'
+++ /dev/null
@@ -1,384 +0,0 @@
-package com.StreamPi.Server.Window.Settings;
-
-import com.StreamPi.Server.UIPropertyBox.UIPropertyBox;
-import com.StreamPi.ActionAPI.ActionProperty.Property.ControlType;
-import com.StreamPi.ActionAPI.ActionProperty.Property.Property;
-import com.StreamPi.ActionAPI.ActionProperty.Property.Type;
-import com.StreamPi.ActionAPI.NormalAction.NormalAction;
-import com.StreamPi.Server.Action.NormalActionPlugins;
-import com.StreamPi.Server.Connection.ServerListener;
-import com.StreamPi.Server.Window.ExceptionAndAlertHandler;
-import com.StreamPi.Util.Exception.MinorException;
-import com.StreamPi.Util.FormHelper.SpaceFiller;
-import com.StreamPi.Util.FormHelper.SpaceFiller.FillerType;
-
-import org.kordamp.ikonli.javafx.FontIcon;
-
-import javafx.application.HostServices;
-import javafx.application.Platform;
-import javafx.geometry.Insets;
-import javafx.geometry.Pos;
-import javafx.scene.Node;
-import javafx.scene.control.*;
-import javafx.scene.layout.HBox;
-import javafx.scene.layout.Priority;
-import javafx.scene.layout.Region;
-import javafx.scene.layout.VBox;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Logger;
-
-public class PluginsSettings extends VBox {
-
- private VBox pluginsSettingsVBox;
-
- private ServerListener serverListener;
-
- private Logger logger;
-
- private ExceptionAndAlertHandler exceptionAndAlertHandler;
-
- private HostServices hostServices;
-
- public PluginsSettings(ExceptionAndAlertHandler exceptionAndAlertHandler, HostServices hostServices)
- {
- getStyleClass().add("plugins_settings");
-
- this.hostServices = hostServices;
- this.exceptionAndAlertHandler = exceptionAndAlertHandler;
- pluginProperties = new ArrayList<>();
- logger = Logger.getLogger(PluginsSettings.class.getName());
-
- setPadding(new Insets(10));
-
- pluginsSettingsVBox = new VBox();
- pluginsSettingsVBox.setSpacing(10.0);
- pluginsSettingsVBox.setAlignment(Pos.TOP_CENTER);
-
- ScrollPane scrollPane = new ScrollPane();
-
- scrollPane.getStyleClass().add("plugins_settings_scroll_pane");
- scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
- scrollPane.maxWidthProperty().bind(widthProperty().multiply(0.8));
-
- pluginsSettingsVBox.prefWidthProperty().bind(scrollPane.widthProperty().subtract(25));
- scrollPane.setContent(pluginsSettingsVBox);
-
- VBox.setVgrow(scrollPane, Priority.ALWAYS);
-
- setAlignment(Pos.TOP_CENTER);
-
-
- saveButton = new Button("Save");
-
- saveButton.setOnAction(event -> onSaveButtonClicked());
-
-
- HBox hBox = new HBox(saveButton);
- hBox.setAlignment(Pos.CENTER_RIGHT);
-
- getChildren().addAll(scrollPane, hBox);
-
- }
-
- private Button saveButton;
-
- public void onSaveButtonClicked()
- {
- try {
- //form validation
- StringBuilder finalErrors = new StringBuilder();
-
- for (PluginProperties p : pluginProperties)
- {
- StringBuilder errors = new StringBuilder();
- for(int j = 0; j < p.getServerPropertyUIBox().size(); j++)
- {
- UIPropertyBox serverProperty = p.getServerPropertyUIBox().get(j);
- Node controlNode = serverProperty.getControlNode();
-
- if (serverProperty.getControlType() == ControlType.TEXT_FIELD)
- {
- String value = ((TextField) controlNode).getText();
- if(serverProperty.getType() == Type.INTEGER)
- {
- try
- {
- Integer.parseInt(value);
- }
- catch (NumberFormatException e)
- {
- errors.append(" -> ").append(serverProperty.getDisplayName()).append(" must be integer.\n");
- }
- }
- else
- {
- if(value.isBlank() && !serverProperty.isCanBeBlank())
- errors.append(" -> ").append(serverProperty.getDisplayName()).append(" cannot be blank.\n");
- }
- }
- }
-
- if(!errors.toString().isBlank())
- {
- finalErrors.append(" * ").append(p.getName()).append("\n").append(errors.toString()).append("\n");
- }
- }
-
- if(!finalErrors.toString().isEmpty())
- {
- throw new MinorException("Form Validation Errors",
- "Please rectify the following errors and try again \n"+finalErrors.toString());
- }
-
- //save
- for (PluginProperties pp : pluginProperties) {
- for (int j = 0; j < pp.getServerPropertyUIBox().size(); j++) {
-
-
- UIPropertyBox serverProperty = pp.getServerPropertyUIBox().get(j);
-
- String rawValue = serverProperty.getRawValue();
-
- NormalActionPlugins.getInstance().getActionFromIndex(pp.getIndex())
- .getServerProperties().get()
- .get(serverProperty.getIndex()).setRawValue(rawValue);
- }
- }
-
-
- NormalActionPlugins.getInstance().saveServerSettings();
-
- NormalActionPlugins.getInstance().initPlugins();
- }
- catch (MinorException e)
- {
- e.printStackTrace();
- exceptionAndAlertHandler.handleMinorException(e);
- }
- }
-
- private ArrayList<PluginProperties> pluginProperties;
-
-
- public void showPluginInitError()
- {
- Platform.runLater(()->{
- pluginsSettingsVBox.getChildren().add(new Label("Plugin init error. Resolve issues and restart."));
- saveButton.setVisible(false);
- });
- }
-
- public void loadPlugins() throws MinorException {
-
- pluginProperties.clear();
-
- List<NormalAction> actions = NormalActionPlugins.getInstance().getPlugins();
-
- System.out.println("asdasdasdasd"+actions.size());
-
- Platform.runLater(()-> pluginsSettingsVBox.getChildren().clear());
-
- if(actions.size() == 0)
- {
- Platform.runLater(()->{
- pluginsSettingsVBox.getChildren().add(new Label("No Plugins Installed."));
- saveButton.setVisible(false);
- });
- return;
- }
- else
- {
- Platform.runLater(()->saveButton.setVisible(true));
- }
-
-
- for(int i = 0; i<actions.size(); i++)
- {
- NormalAction action = actions.get(i);
-
- if(!action.isVisibleInServerSettingsPane())
- continue;
-
-
- Label headingLabel = new Label(action.getName());
- headingLabel.getStyleClass().add("settings_plugins_each_action_heading");
-
- HBox headerHBox = new HBox(headingLabel);
-
-
- if (action.getHelpLink()!=null)
- {
- Button helpButton = new Button();
- FontIcon questionIcon = new FontIcon("fas-question");
- questionIcon.getStyleClass().add("settings_plugins_plugin_help_icon");
- helpButton.setGraphic(questionIcon);
- helpButton.setOnAction(event -> hostServices.showDocument(action.getHelpLink()));
-
- headerHBox.getChildren().addAll(new SpaceFiller(FillerType.HBox),helpButton);
- }
-
-
-
- Label authorLabel = new Label(action.getAuthor());
-
- Label moduleLabel = new Label(action.getModuleName());
-
- Label versionLabel = new Label("Version : "+action.getVersion().getText());
-
- VBox serverPropertiesVBox = new VBox();
- serverPropertiesVBox.setSpacing(10.0);
-
- List<Property> serverProperties = action.getServerProperties().get();
-
- ArrayList<UIPropertyBox> serverPropertyArrayList = new ArrayList<>();
-
-
- for(int j =0; j<serverProperties.size(); j++)
- {
- Property eachProperty = serverProperties.get(j);
-
- if(!eachProperty.isVisible())
- continue;
-
-
- Label label = new Label(eachProperty.getDisplayName());
-
- Region region = new Region();
- HBox.setHgrow(region, Priority.ALWAYS);
-
- HBox hBox = new HBox(label, new SpaceFiller(SpaceFiller.FillerType.HBox));
- //hBox.setId(j+"");
-
- Node controlNode = null;
-
- if(eachProperty.getControlType() == ControlType.COMBO_BOX)
- {
- ComboBox<String> comboBox = new ComboBox<>();
- comboBox.getItems().addAll(eachProperty.getListValue());
- comboBox.getSelectionModel().select(eachProperty.getSelectedIndex());
- hBox.getChildren().add(comboBox);
-
- controlNode = comboBox;
- }
- else if(eachProperty.getControlType() == ControlType.TEXT_FIELD)
- {
- TextField textField = new TextField(eachProperty.getRawValue());
-
- hBox.getChildren().add(textField);
-
- controlNode = textField;
- }
- else if(eachProperty.getControlType() == ControlType.TOGGLE)
- {
- ToggleButton toggleButton = new ToggleButton();
- toggleButton.setSelected(eachProperty.getBoolValue());
-
- if(eachProperty.getBoolValue())
- toggleButton.setText("ON");
- else
- toggleButton.setText("OFF");
-
- toggleButton.selectedProperty().addListener((observableValue, aBoolean, t1) -> {
- if(t1)
- toggleButton.setText("ON");
- else
- toggleButton.setText("OFF");
- });
-
- hBox.getChildren().add(toggleButton);
-
- controlNode = toggleButton;
- }
- else if(eachProperty.getControlType() == ControlType.SLIDER_DOUBLE)
- {
- Slider slider = new Slider();
- slider.setValue(eachProperty.getDoubleValue());
- slider.setMax(eachProperty.getMaxDoubleValue());
- slider.setMin(eachProperty.getMinDoubleValue());
-
- hBox.getChildren().add(slider);
-
- controlNode = slider;
- }
- else if(eachProperty.getControlType() == ControlType.SLIDER_INTEGER)
- {
- Slider slider = new Slider();
- slider.setValue(eachProperty.getIntValue());
-
- slider.setMax(eachProperty.getMaxIntValue());
- slider.setMin(eachProperty.getMinIntValue());
- slider.setBlockIncrement(1.0);
- slider.setSnapToTicks(true);
-
- hBox.getChildren().add(slider);
-
- controlNode = slider;
- }
-
-
- UIPropertyBox serverProperty = new UIPropertyBox(j, eachProperty.getDisplayName(), controlNode, eachProperty.getControlType(), eachProperty.getType(), eachProperty.isCanBeBlank());
-
- serverPropertyArrayList.add(serverProperty);
-
- serverPropertiesVBox.getChildren().add(hBox);
-
- }
-
- PluginProperties pp = new PluginProperties(i, serverPropertyArrayList, action.getName());
-
- pluginProperties.add(pp);
-
-
-
- Region region1 = new Region();
- region1.setPrefHeight(5);
-
-
- Platform.runLater(()->{
- VBox vBox = new VBox();
- vBox.setSpacing(5.0);
- vBox.getChildren().addAll(headerHBox, authorLabel, moduleLabel, versionLabel, serverPropertiesVBox);
-
- if(action.getButtonBar()!=null)
- vBox.getChildren().add(new HBox(new SpaceFiller(SpaceFiller.FillerType.HBox), action.getButtonBar()));
-
- vBox.getChildren().add(region1);
- //vBox.setId(i+"");
-
- vBox.getStyleClass().add("settings_plugins_each_action");
-
- pluginsSettingsVBox.getChildren().add(vBox);
-
- });
- }
- }
-
- public class PluginProperties
- {
- private int index;
- private ArrayList<UIPropertyBox> serverProperty;
- private String name;
-
- public PluginProperties(int index, ArrayList<UIPropertyBox> serverProperty, String name)
- {
- this.index = index;
- this.serverProperty = serverProperty;
- this.name = name;
- }
-
- public String getName()
- {
- return name;
- }
-
- public int getIndex() {
- return index;
- }
-
- public ArrayList<UIPropertyBox> getServerPropertyUIBox() {
- return serverProperty;
- }
- }
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/Settings/SettingsBase.java'
+++ /dev/null
@@ -1,101 +0,0 @@
-package com.StreamPi.Server.Window.Settings;
-
-import com.StreamPi.Server.Connection.ServerListener;
-import com.StreamPi.Server.Window.ExceptionAndAlertHandler;
-import com.StreamPi.ThemeAPI.Theme;
-import javafx.application.HostServices;
-import javafx.geometry.Insets;
-import javafx.geometry.Pos;
-import javafx.scene.CacheHint;
-import javafx.scene.control.*;
-import javafx.scene.layout.Priority;
-import javafx.scene.layout.VBox;
-
-public class SettingsBase extends VBox {
-
- private TabPane tabPane;
-
- private GeneralSettings generalSettings;
- private PluginsSettings pluginsSettings;
- private ThemesSettings themesSettings;
- private ClientsSettings clientsSettings;
-
- private Button closeButton;
-
- private HostServices hostServices;
- private ExceptionAndAlertHandler exceptionAndAlertHandler;
-
- public SettingsBase(HostServices hostServices, ExceptionAndAlertHandler exceptionAndAlertHandler,
- ServerListener serverListener)
- {
- this.exceptionAndAlertHandler = exceptionAndAlertHandler;
- this.hostServices = hostServices;
-
- tabPane = new TabPane();
- tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
- VBox.setVgrow(tabPane, Priority.ALWAYS);
-
- Tab generalSettingsTab = new Tab("General");
- generalSettings = new GeneralSettings(exceptionAndAlertHandler, serverListener, hostServices);
- generalSettingsTab.setContent(generalSettings);
-
- Tab pluginsSettingsTab = new Tab("Plugins");
- pluginsSettings = new PluginsSettings(exceptionAndAlertHandler, hostServices);
- pluginsSettingsTab.setContent(pluginsSettings);
-
- Tab themesSettingsTab = new Tab("Themes");
- themesSettings = new ThemesSettings(hostServices);
- themesSettingsTab.setContent(themesSettings);
-
- Tab clientsSettingsTab = new Tab("Clients");
- clientsSettings = new ClientsSettings(exceptionAndAlertHandler, serverListener);
- clientsSettingsTab.setContent(clientsSettings);
-
-
- Tab aboutTab = new Tab("About");
- aboutTab.setContent(new About(hostServices));
-
- tabPane.getTabs().addAll(generalSettingsTab, pluginsSettingsTab, themesSettingsTab, clientsSettingsTab, aboutTab);
-
- setAlignment(Pos.TOP_RIGHT);
-
- closeButton = new Button("Close");
- VBox.setMargin(closeButton, new Insets(10.0));
-
- getChildren().addAll(tabPane, closeButton);
-
- setCache(true);
- setCacheHint(CacheHint.SPEED);
- }
-
- public void setDefaultTabToGeneral()
- {
- tabPane.getSelectionModel().selectFirst();
- }
-
- public Button getCloseButton()
- {
- return closeButton;
- }
-
- public GeneralSettings getGeneralSettings()
- {
- return generalSettings;
- }
-
- public PluginsSettings getPluginsSettings()
- {
- return pluginsSettings;
- }
-
- public ThemesSettings getThemesSettings()
- {
- return themesSettings;
- }
-
- public ClientsSettings getClientsSettings()
- {
- return clientsSettings;
- }
-
-}
--- 'a/src/main/java/com/StreamPi/Server/Window/Settings/ThemesSettings.java'
+++ /dev/null
@@ -1,200 +0,0 @@
-package com.StreamPi.Server.Window.Settings;
-
-import com.StreamPi.ActionAPI.Action.Action;
-import com.StreamPi.ActionAPI.ActionProperty.Property.ControlType;
-import com.StreamPi.ActionAPI.ActionProperty.Property.Property;
-import com.StreamPi.ActionAPI.NormalAction.NormalAction;
-import com.StreamPi.Server.Action.NormalActionPlugins;
-import com.StreamPi.Server.Connection.ServerListener;
-import com.StreamPi.Server.Controller.Controller;
-import com.StreamPi.Server.IO.Config;
-import com.StreamPi.ThemeAPI.Theme;
-import com.StreamPi.ThemeAPI.Themes;
-import com.StreamPi.Util.Exception.MinorException;
-import com.StreamPi.Util.Exception.SevereException;
-import com.StreamPi.Util.FormHelper.SpaceFiller;
-import javafx.application.HostServices;
-import javafx.application.Platform;
-import javafx.concurrent.Task;
-import javafx.geometry.Insets;
-import javafx.geometry.Pos;
-import javafx.scene.control.*;
-import javafx.scene.layout.HBox;
-import javafx.scene.layout.Priority;
-import javafx.scene.layout.Region;
-import javafx.scene.layout.VBox;
-import org.kordamp.ikonli.javafx.FontIcon;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Logger;
-
-public class ThemesSettings extends VBox
-{
- private VBox themesSettingsVBox;
-
- private Controller controller;
-
- private Logger logger;
- private HostServices hostServices;
-
- public ThemesSettings(HostServices hostServices)
- {
- this.hostServices = hostServices;
- getStyleClass().add("themes_settings");
- logger = Logger.getLogger(ThemesSettings.class.getName());
-
- setPadding(new Insets(10));
-
- themesSettingsVBox = new VBox();
- themesSettingsVBox.setSpacing(10.0);
- themesSettingsVBox.setAlignment(Pos.TOP_CENTER);
-
- ScrollPane scrollPane = new ScrollPane();
- scrollPane.getStyleClass().add("themes_settings_scroll_pane");
- scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
- scrollPane.maxWidthProperty().bind(widthProperty().multiply(0.8));
-
- themesSettingsVBox.prefWidthProperty().bind(scrollPane.widthProperty().subtract(10));
- scrollPane.setContent(themesSettingsVBox);
-
- VBox.setVgrow(scrollPane, Priority.ALWAYS);
-
- setAlignment(Pos.TOP_CENTER);
-
- getChildren().addAll(scrollPane);
-
- toggleButtons = new ArrayList<>();
-
- }
-
- public void setController(Controller controller)
- {
- this.controller = controller;
- }
-
- private Themes themes;
- private String currentThemeFullName;
-
- public void setThemes(Themes themes)
- {
- this.themes = themes;
- }
-
- public void setCurrentThemeFullName(String currentThemeFullName)
- {
- this.currentThemeFullName = currentThemeFullName;
- }
-
- private ArrayList<ToggleButton> toggleButtons;
-
- public void loadThemes()
- {
- toggleButtons.clear();
-
- Platform.runLater(()-> themesSettingsVBox.getChildren().clear());
-
-
- for(int i = 0; i<themes.getThemeList().size(); i++)
- {
- Theme theme = themes.getThemeList().get(i);
-
-
- Label shortNameLabel = new Label(theme.getShortName());
- shortNameLabel.getStyleClass().add("settings_themes_each_theme_heading");
-
- Label authorLabel = new Label(theme.getAuthor());
-
- Label fullNameLabel = new Label(theme.getFullName());
-
-
- HBox topRowHBox = new HBox(shortNameLabel);
-
- if(theme.getWebsite() != null)
- {
- Button helpButton = new Button();
- FontIcon questionIcon = new FontIcon("fas-question");
- questionIcon.getStyleClass().add("settings_themes_theme_help_icon");
- helpButton.setGraphic(questionIcon);
- helpButton.setOnAction(event -> hostServices.showDocument(theme.getWebsite()));
-
- topRowHBox.getChildren().addAll(new SpaceFiller(SpaceFiller.FillerType.HBox), helpButton);
- }
-
-
-
- Label versionLabel = new Label("Version : "+theme.getVersion().getText());
-
- ToggleButton toggleButton = new ToggleButton();
-
- toggleButton.setSelected(theme.getFullName().equals(currentThemeFullName));
- toggleButton.setId(theme.getFullName());
-
-
- if(theme.getFullName().equals(currentThemeFullName))
- {
- toggleButton.setText("ON");
- toggleButton.setSelected(true);
- toggleButton.setDisable(true);
- }
- else
- {
- toggleButton.setText("OFF");
- }
-
- toggleButton.setOnAction(event -> {
- ToggleButton toggleButton1 = (ToggleButton) event.getSource();
-
-
- toggleButton.setText("ON");
-
- try {
- Config.getInstance().setCurrentThemeFullName(toggleButton1.getId());
- Config.getInstance().save();
-
-
- for(ToggleButton toggleButton2 : toggleButtons)
- {
- if(toggleButton2.getId().equals(Config.getInstance().getCurrentThemeFullName()))
- {
- toggleButton2.setDisable(true);
- toggleButton2.setText("ON");
- toggleButton2.setSelected(true);
- }
- else
- {
- toggleButton2.setDisable(false);
- toggleButton2.setText("OFF");
- toggleButton2.setSelected(false);
- }
- }
-
- controller.initThemes();
- }
- catch (SevereException e)
- {
- controller.handleSevereException(e);
- }
- });
-
- HBox hBox = new HBox(toggleButton);
-
- Region region1 = new Region();
- region1.setPrefHeight(5);
-
- hBox.setAlignment(Pos.TOP_RIGHT);
-
- VBox vBox = new VBox(topRowHBox, authorLabel, versionLabel, fullNameLabel, hBox, region1);
- vBox.setSpacing(5.0);
-
-
- vBox.getStyleClass().add("settings_themes_each_theme");
-
- Platform.runLater(()->themesSettingsVBox.getChildren().add(vBox));
-
-
- toggleButtons.add(toggleButton);
- }
-
- }
-}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/Main.java
@@ -0,0 +1,62 @@
+/*
+Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macropad
+Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Written by : Debayan Sutradhar (rnayabed)
+*/
+
+
+package com.stream_pi.server;
+
+import com.stream_pi.server.controller.Controller;
+import com.stream_pi.server.info.ServerInfo;
+
+import javafx.application.Application;
+import javafx.scene.Scene;
+import javafx.stage.Stage;
+
+public class Main extends Application {
+
+ /**
+ * First method to be called
+ * This method first parses all the available command line arguments passed.
+ * Then a new instance of controller is created, and then initialised.
+ */
+ public void start(Stage stage) {
+
+ for(String eachArg : getParameters().getRaw())
+ {
+ String[] r = eachArg.split("=");
+ if(r[0].equals("-DStreamPi.startupRunnerFileName"))
+ ServerInfo.getInstance().setRunnerFileName(r[1]);
+ else if(r[0].equals("-DStreamPi.startupMode"))
+ ServerInfo.getInstance().setStartMinimised(r[1].equals("min"));
+ }
+
+
+ Controller d = new Controller();
+ Scene s = new Scene(d);
+ stage.setScene(s);
+ d.setHostServices(getHostServices());
+ d.init();
+ }
+
+ /**
+ * This is a fallback. Called in some JVMs.
+ * This method just sends the command line arguments to JavaFX Application
+ */
+ public static void main(String[] args)
+ {
+
+ launch(args);
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/action/NormalActionPlugins.java
@@ -0,0 +1,571 @@
+/*
+Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macropad
+Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Written by : Debayan Sutradhar (rnayabed)
+*/
+
+package com.stream_pi.server.action;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import com.stream_pi.actionapi.action.Action;
+import com.stream_pi.actionapi.action.ActionType;
+import com.stream_pi.actionapi.action.PropertySaver;
+import com.stream_pi.actionapi.action.ServerConnection;
+import com.stream_pi.actionapi.actionproperty.ServerProperties;
+import com.stream_pi.actionapi.actionproperty.property.Property;
+import com.stream_pi.actionapi.actionproperty.property.Type;
+import com.stream_pi.actionapi.normalaction.NormalAction;
+import com.stream_pi.util.exception.MinorException;
+import com.stream_pi.util.exception.SevereException;
+import com.stream_pi.util.exception.StreamPiException;
+import com.stream_pi.util.version.Version;
+import com.stream_pi.util.xmlconfighelper.XMLConfigHelper;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import java.io.File;
+import java.lang.module.*;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+import org.w3c.dom.Element;
+
+public class NormalActionPlugins
+{
+ private static NormalActionPlugins instance = null;
+ private final Logger logger;
+
+ private File configFile;
+ private Document document;
+
+ private static String pluginsLocation = null;
+
+
+ /**
+ * Singleton class instance getter. Creates new one, when asked for the first time
+ *
+ * @return returns instance of NormalActionPlugins (one and only, always)
+ */
+ public static synchronized NormalActionPlugins getInstance()
+ {
+ if(instance == null)
+ {
+ instance = new NormalActionPlugins();
+ }
+
+ return instance;
+ }
+
+ /**
+ * Sets the folder location where the plugin JARs and their dependencies are stored
+ *
+ * @param location Folder location
+ */
+ public static void setPluginsLocation(String location)
+ {
+ pluginsLocation = location;
+ }
+
+ /**
+ * Private constructor
+ */
+ private NormalActionPlugins()
+ {
+ logger = Logger.getLogger(NormalActionPlugins.class.getName());
+ normalPluginsHashmap = new HashMap<>();
+ }
+
+ /**
+ * init Method
+ */
+ public void init() throws SevereException, MinorException
+ {
+ registerPlugins();
+ initPlugins();
+ }
+
+ /**
+ * Used to fetch list of all external Plugins
+ *
+ * @return List of plugins
+ */
+ public List<NormalAction> getPlugins()
+ {
+ return normalPlugins;
+ }
+
+ /**
+ * Returns a plugin by its module name
+ *
+ * @param name Module Name
+ * @return The plugin. If not found, then null is returned
+ */
+ public NormalAction getPluginByModuleName(String name)
+ {
+ logger.info("Plugin being requested : "+name);
+ Integer index = normalPluginsHashmap.getOrDefault(name, -1);
+ if(index != -1)
+ {
+ return normalPlugins.get(index);
+ }
+
+ return null;
+ }
+
+ private List<NormalAction> normalPlugins = null;
+ HashMap<String, Integer> normalPluginsHashmap;
+
+ /**
+ * Used to register plugins from plugin location
+ */
+ public void registerPlugins() throws SevereException, MinorException
+ {
+ logger.info("Registering external plugins from "+pluginsLocation+" ...");
+
+ try
+ {
+ configFile = new File(pluginsLocation+"/config.xml");
+ DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+ document = docBuilder.parse(configFile);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ throw new SevereException("Plugins","Error reading plugins config.xml. Cannot continue.");
+ }
+
+ ArrayList<NormalAction> errorModules = new ArrayList<>();
+ ArrayList<String> errorModuleError = new ArrayList<>();
+
+ ArrayList<Action> pluginsConfigs = new ArrayList<>();
+
+ NodeList actionsNode = document.getElementsByTagName("actions").item(0).getChildNodes();
+
+ for(int i =0;i<actionsNode.getLength();i++)
+ {
+ Node eachActionNode = actionsNode.item(i);
+
+ if(eachActionNode.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+
+ if(!eachActionNode.getNodeName().equals("action"))
+ continue;
+
+ Element eachActionElement = (Element) eachActionNode;
+
+
+
+ String name;
+ Version version;
+ try
+ {
+ name = XMLConfigHelper.getStringProperty(eachActionElement, "module-name");
+ version = new Version(XMLConfigHelper.getStringProperty(eachActionElement, "version"));
+ }
+ catch (Exception e)
+ {
+ logger.log(Level.WARNING, "Skipping configuration because invalid ...");
+ e.printStackTrace();
+ continue;
+ }
+
+ ServerProperties serverProperties = new ServerProperties();
+
+ NodeList serverPropertiesNodeList = eachActionElement.getElementsByTagName("properties").item(0).getChildNodes();
+
+ for(int j = 0;j<serverPropertiesNodeList.getLength();j++)
+ {
+ Node eachPropertyNode = serverPropertiesNodeList.item(j);
+
+
+ if(eachPropertyNode.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+
+ if(!eachPropertyNode.getNodeName().equals("property"))
+ continue;
+
+
+ Element eachPropertyElement = (Element) eachPropertyNode;
+
+ try
+ {
+ Property property = new Property(XMLConfigHelper.getStringProperty(eachPropertyElement, "name"), Type.STRING);
+ property.setRawValue(XMLConfigHelper.getStringProperty(eachPropertyElement, "value"));
+
+ serverProperties.addProperty(property);
+ }
+ catch (Exception e)
+ {
+ logger.log(Level.WARNING, "Skipping property because invalid ...");
+ e.printStackTrace();
+ }
+ }
+
+ Action action = new Action(ActionType.NORMAL);
+
+ action.setModuleName(name);
+ action.setVersion(version);
+ action.getServerProperties().set(serverProperties);
+
+ pluginsConfigs.add(action);
+ }
+
+ logger.info("Size : "+pluginsConfigs.size());
+
+ Path pluginsDir = Paths.get(pluginsLocation); // Directory with plugins JARs
+ try
+ {
+ // Search for plugins in the plugins directory
+ ModuleFinder pluginsFinder = ModuleFinder.of(pluginsDir);
+
+ // Find all names of all found plugin modules
+ List<String> p = pluginsFinder
+ .findAll()
+ .stream()
+ .map(ModuleReference::descriptor)
+ .map(ModuleDescriptor::name)
+ .collect(Collectors.toList());
+
+ // Create configuration that will resolve plugin modules
+ // (verify that the graph of modules is correct)
+ Configuration pluginsConfiguration = ModuleLayer
+ .boot()
+ .configuration()
+ .resolve(pluginsFinder, ModuleFinder.of(), p);
+
+ // Create a module layer for plugins
+ ModuleLayer layer = ModuleLayer
+ .boot()
+ .defineModulesWithOneLoader(pluginsConfiguration, ClassLoader.getSystemClassLoader());
+
+ logger.info("Loading plugins from jar ...");
+ // Now you can use the new module layer to find service implementations in it
+ normalPlugins = ServiceLoader
+ .load(layer, NormalAction.class).stream()
+ .map(ServiceLoader.Provider::get)
+ .collect(Collectors.toList());
+
+ logger.info("...Done!");
+
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+
+ throw new MinorException("Error", "Error loading modules\n"+e.getMessage()+"\nPlease fix the errors. Other plugins wont be loaded.");
+ }
+
+
+ sortedPlugins = new HashMap<>();
+
+ for (NormalAction eachPlugin : normalPlugins)
+ {
+ try
+ {
+ eachPlugin.setPropertySaver(propertySaver);
+ eachPlugin.setServerConnection(serverConnection);
+ eachPlugin.initProperties();
+
+ Action foundAction = null;
+ for (Action action : pluginsConfigs) {
+ if (action.getModuleName().equals(eachPlugin.getModuleName())
+ && action.getVersion().isEqual(eachPlugin.getVersion())) {
+
+ foundAction = action;
+
+ List<Property> eachPluginStoredProperties = action.getServerProperties().get();
+ List<Property> eachPluginCodeProperties = eachPlugin.getServerProperties().get();
+
+
+ for (int i =0;i< eachPluginCodeProperties.size(); i++) {
+
+ Property eachPluginCodeProperty = eachPluginCodeProperties.get(i);
+
+ Property foundProp = null;
+ for (Property eachPluginStoredProperty : eachPluginStoredProperties) {
+ if (eachPluginCodeProperty.getName().equals(eachPluginStoredProperty.getName())) {
+ eachPluginCodeProperty.setRawValue(eachPluginStoredProperty.getRawValue());
+ foundProp = eachPluginStoredProperty;
+ }
+ }
+
+ eachPluginCodeProperties.set(i, eachPluginCodeProperty);
+
+ if (foundProp != null) {
+ eachPluginStoredProperties.remove(foundProp);
+ }
+ }
+
+
+ eachPlugin.getServerProperties().set(eachPluginCodeProperties);
+
+ break;
+ }
+ }
+
+ if (foundAction != null)
+ pluginsConfigs.remove(foundAction);
+ else
+ {
+ List<Property> eachPluginStoredProperties = eachPlugin.getServerProperties().get();
+ for(Property property :eachPluginStoredProperties)
+ {
+ if(property.getType() == Type.STRING || property.getType() == Type.INTEGER || property.getType() == Type.DOUBLE)
+ property.setRawValue(property.getDefaultRawValue());
+ }
+ }
+
+
+
+ if (!sortedPlugins.containsKey(eachPlugin.getCategory())) {
+ ArrayList<NormalAction> actions = new ArrayList<>();
+
+ sortedPlugins.put(eachPlugin.getCategory(), actions);
+ }
+
+ sortedPlugins.get(eachPlugin.getCategory()).add(eachPlugin);
+
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ errorModules.add(eachPlugin);
+ errorModuleError.add(e.getMessage());
+ }
+ }
+
+ try {
+ saveServerSettings();
+ } catch (MinorException e) {
+ e.printStackTrace();
+ }
+
+ logger.log(Level.INFO, "All plugins registered!");
+
+ if(errorModules.size() > 0)
+ {
+ StringBuilder errors = new StringBuilder("The following action modules could not be loaded:");
+ for(int i = 0; i<errorModules.size(); i++)
+ {
+ normalPlugins.remove(errorModules.get(i));
+ errors.append("\n * ").append(errorModules.get(i).getModuleName()).append("\n(")
+ .append(errorModuleError.get(i)).append(")");
+ }
+
+ throw new MinorException("Plugins", errors.toString());
+ }
+
+
+ for(int i = 0;i<normalPlugins.size();i++)
+ {
+ normalPluginsHashmap.put(normalPlugins.get(i).getModuleName(), i);
+ }
+ }
+
+ /**
+ * Used to init plugins
+ */
+ public void initPlugins() throws MinorException
+ {
+ StringBuilder errors = new StringBuilder("There were errors registering the following plugins. As a result, they have been omitted : ");
+ boolean isError = false;
+
+ for(NormalAction eachPlugin : normalPlugins)
+ {
+ try
+ {
+ eachPlugin.initAction();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ isError = true;
+ errors.append("\n* ")
+ .append(eachPlugin.getName())
+ .append(" - ")
+ .append(eachPlugin.getModuleName())
+ .append("\n");
+
+ if(e instanceof StreamPiException)
+ errors.append(((MinorException) e).getShortMessage());
+
+ errors.append("\n");
+ }
+ }
+
+ if(isError)
+ {
+ throw new MinorException("Plugin init error", errors.toString());
+ }
+ }
+
+ HashMap<String, ArrayList<NormalAction>> sortedPlugins;
+
+ /**
+ * Gets list of sorted plugins
+ *
+ * @return Hashmap with category key, and list of plugins of each category
+ */
+ public HashMap<String, ArrayList<NormalAction>> getSortedPlugins()
+ {
+ return sortedPlugins;
+ }
+
+ /**
+ * @return Gets actions element from the config.xml in plugins folder
+ */
+ private Element getActionsElement()
+ {
+ return (Element) document.getElementsByTagName("actions").item(0);
+ }
+
+ /**
+ * Saves ServerProperties of every plugin in config.xml in plugins folder
+ *
+ * @throws MinorException Thrown when failed to save settings
+ */
+ public void saveServerSettings() throws MinorException
+ {
+ XMLConfigHelper.removeChilds(getActionsElement());
+
+ for(NormalAction normalAction : normalPlugins)
+ {
+ Element actionElement = document.createElement("action");
+ getActionsElement().appendChild(actionElement);
+
+ Element moduleNameElement = document.createElement("module-name");
+ moduleNameElement.setTextContent(normalAction.getModuleName());
+ actionElement.appendChild(moduleNameElement);
+
+
+ Element versionElement = document.createElement("version");
+ versionElement.setTextContent(normalAction.getVersion().getText());
+ actionElement.appendChild(versionElement);
+
+ Element propertiesElement = document.createElement("properties");
+ actionElement.appendChild(propertiesElement);
+
+ for(String key : normalAction.getServerProperties().getNames())
+ {
+ for(Property eachProperty : normalAction.getServerProperties().getMultipleProperties(key))
+ {
+ Element propertyElement = document.createElement("property");
+ propertiesElement.appendChild(propertyElement);
+
+ Element nameElement = document.createElement("name");
+ nameElement.setTextContent(eachProperty.getName());
+ propertyElement.appendChild(nameElement);
+
+ Element valueElement = document.createElement("value");
+ valueElement.setTextContent(eachProperty.getRawValue());
+ propertyElement.appendChild(valueElement);
+ }
+ }
+ }
+
+ save();
+ }
+
+ private PropertySaver propertySaver = null;
+
+ /**
+ * Set PropertySaver class
+ * @param propertySaver instance of PropertySaver
+ */
+ public void setPropertySaver(PropertySaver propertySaver)
+ {
+ this.propertySaver = propertySaver;
+ }
+
+ private ServerConnection serverConnection = null;
+
+ /**
+ * Set setServerConnection class
+ * @param serverConnection instance of ServerConnection
+ */
+ public void setServerConnection(ServerConnection serverConnection)
+ {
+ this.serverConnection = serverConnection;
+ }
+
+ /**
+ * Get plugin from index from list
+ *
+ * @param index of plugin
+ * @return found plugin
+ */
+ public NormalAction getActionFromIndex(int index)
+ {
+ return normalPlugins.get(index);
+ }
+
+ /**
+ * Calls onShutDown method in every plugin
+ */
+ public void shutDownActions()
+ {
+ if(normalPlugins != null)
+ {
+ for(NormalAction eachPlugin : normalPlugins)
+ {
+ try
+ {
+ eachPlugin.onShutDown();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ normalPlugins.clear();
+ }
+ }
+
+ /**
+ * Saves all Server Properties of each Plugin in config.xml in Plugins folder
+ * @throws MinorException thrown when failed to save
+ */
+ public void save() throws MinorException
+ {
+ try
+ {
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ Result output = new StreamResult(configFile);
+ Source input = new DOMSource(document);
+
+ transformer.transform(input, output);
+ }
+ catch (Exception e)
+ {
+ throw new MinorException("Config", "unable to save server plugins settings");
+ }
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/client/Client.java
@@ -0,0 +1,189 @@
+/*
+Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macropad
+Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Written by : Debayan Sutradhar (rnayabed)
+*/
+
+package com.stream_pi.server.client;
+
+import com.stream_pi.util.platform.Platform;
+import com.stream_pi.util.platform.ReleaseStatus;
+import com.stream_pi.util.version.Version;
+
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+public class Client {
+ private String nickName;
+ private final SocketAddress remoteSocketAddress;
+ private final Platform platform;
+ private final Version version;
+ private final Version commStandardVersion;
+ private final Version themeAPIVersion;
+ private final ReleaseStatus releaseStatus;
+
+ private double startupDisplayHeight, startupDisplayWidth;
+
+ private final HashMap<String,ClientProfile> profiles;
+
+ private final HashMap<String,ClientTheme> themes;
+
+ private String defaultProfileID;
+ private String defaultThemeFullName;
+
+ public Client(Version version, ReleaseStatus releaseStatus, Version commStandardVersion, Version themeAPIVersion, String nickName, Platform platform, SocketAddress remoteSocketAddress)
+ {
+ this.version = version;
+ this.releaseStatus = releaseStatus;
+ this.commStandardVersion = commStandardVersion;
+ this.themeAPIVersion = themeAPIVersion;
+ this.nickName = nickName;
+ this.remoteSocketAddress = remoteSocketAddress;
+ this.platform = platform;
+ this.profiles = new HashMap<>();
+ this.themes = new HashMap<>();
+ }
+
+ public ReleaseStatus getReleaseStatus() {
+ return releaseStatus;
+ }
+
+ public void setDefaultThemeFullName(String defaultThemeFullName) {
+ this.defaultThemeFullName = defaultThemeFullName;
+ }
+
+ public String getDefaultThemeFullName() {
+ return defaultThemeFullName;
+ }
+
+ public void setDefaultProfileID(String ID)
+ {
+ defaultProfileID = ID;
+ }
+
+ public void addTheme(ClientTheme clientTheme) throws CloneNotSupportedException
+ {
+ themes.put(clientTheme.getThemeFullName(), (ClientTheme) clientTheme.clone());
+ }
+
+ public ArrayList<ClientTheme> getThemes()
+ {
+ ArrayList<ClientTheme> clientThemes = new ArrayList<>();
+ for(String clientTheme : themes.keySet())
+ {
+ clientThemes.add(themes.get(clientTheme));
+ }
+ return clientThemes;
+ }
+
+ public ClientTheme getThemeByFullName(String fullName)
+ {
+ return themes.getOrDefault(fullName, null);
+ }
+
+ public String getDefaultProfileID()
+ {
+ return defaultProfileID;
+ }
+
+ //client Profiles
+
+ public void setNickName(String nickName)
+ {
+ this.nickName = nickName;
+ }
+
+ public List<ClientProfile> getAllClientProfiles()
+ {
+ ArrayList<ClientProfile> clientProfiles = new ArrayList<>();
+ for(String profile : profiles.keySet())
+ clientProfiles.add(profiles.get(profile));
+ return clientProfiles;
+ }
+
+ public void removeProfileFromID(String ID)
+ {
+ profiles.remove(ID);
+ }
+
+ public void addProfile(ClientProfile clientProfile) throws CloneNotSupportedException {
+ profiles.put(clientProfile.getID(), (ClientProfile) clientProfile.clone());
+ }
+
+ public synchronized ClientProfile getProfileByID(String ID) {
+ return profiles.getOrDefault(ID, null);
+ }
+
+ public SocketAddress getRemoteSocketAddress()
+ {
+ return remoteSocketAddress;
+ }
+
+ public Platform getPlatform()
+ {
+ return platform;
+ }
+
+ public String getNickName()
+ {
+ return nickName;
+ }
+
+ public Version getVersion()
+ {
+ return version;
+ }
+
+ public Version getCommStandardVersion()
+ {
+ return commStandardVersion;
+ }
+
+ public Version getThemeAPIVersion()
+ {
+ return themeAPIVersion;
+ }
+
+ public double getStartupDisplayHeight()
+ {
+ return startupDisplayHeight;
+ }
+
+ public double getStartupDisplayWidth()
+ {
+ return startupDisplayWidth;
+ }
+
+ public void setStartupDisplayHeight(double height)
+ {
+ startupDisplayHeight = height;
+ }
+
+ public void setStartupDisplayWidth(double width)
+ {
+ startupDisplayWidth = width;
+ }
+
+ private int getMaxRows(int eachActionSize)
+ {
+ return (int) (startupDisplayHeight / eachActionSize);
+ }
+
+ public int getMaxCols(int eachActionSize)
+ {
+ return (int) (startupDisplayWidth / eachActionSize);
+ }
+
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/client/ClientProfile.java
@@ -0,0 +1,133 @@
+/*
+Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macropad
+Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Written by : Debayan Sutradhar (rnayabed)
+*/
+
+package com.stream_pi.server.client;
+
+import com.stream_pi.actionapi.action.Action;
+
+import java.util.HashMap;
+import java.util.Set;
+import java.util.UUID;
+
+public class ClientProfile implements Cloneable {
+
+ private String name, ID;
+
+ private int rows, cols, actionSize, actionGap;
+
+ private final HashMap<String, Action> actions;
+
+ public ClientProfile(String name, String ID, int rows, int cols, int actionSize, int actionGap)
+ {
+ this.actions = new HashMap<>();
+ this.ID = ID;
+ this.name = name;
+ this.rows = rows;
+ this.cols = cols;
+ this.actionGap = actionGap;
+ this.actionSize = actionSize;
+ }
+
+ public ClientProfile(String name, int rows, int cols, int actionSize, int actionGap)
+ {
+ this(name, UUID.randomUUID().toString(), rows, cols, actionSize, actionGap);
+ }
+
+ public Action getActionByID(String ID)
+ {
+ return actions.get(ID);
+ }
+
+ public void removeActionByID(String ID)
+ {
+ actions.remove(ID);
+ }
+
+
+ public Set<String> getActionsKeySet() {
+ return actions.keySet();
+ }
+
+ public synchronized void addAction(Action action) throws CloneNotSupportedException {
+ actions.put(action.getID(), action.clone());
+ }
+
+ public String getID()
+ {
+ return ID;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public int getRows()
+ {
+ return rows;
+ }
+
+ public int getCols()
+ {
+ return cols;
+ }
+
+ public int getActionSize()
+ {
+ return actionSize;
+ }
+
+ public int getActionGap()
+ {
+ return actionGap;
+ }
+
+ public void setRows(int rows)
+ {
+ this.rows = rows;
+ }
+
+ public void setCols(int cols)
+ {
+ this.cols = cols;
+ }
+
+ public void setID(String ID)
+ {
+ this.ID = ID;
+ }
+
+ public void setActionSize(int actionSize)
+ {
+ this.actionSize = actionSize;
+ }
+
+ public void setActionGap(int actionGap)
+ {
+ this.actionGap = actionGap;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+
+ public Object clone() throws CloneNotSupportedException
+ {
+ return super.clone();
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/client/ClientTheme.java
@@ -0,0 +1,42 @@
+package com.stream_pi.server.client;
+
+public class ClientTheme implements Cloneable
+{
+ public String themeFullName;
+ public String shortName;
+ public String author;
+ public String version;
+
+ public ClientTheme(String themeFullName, String shortName,
+ String author, String version)
+ {
+ this.themeFullName = themeFullName;
+ this.shortName = shortName;
+ this.author = author;
+ this.version = version;
+ }
+
+ public String getThemeFullName()
+ {
+ return themeFullName;
+ }
+
+ public String getShortName()
+ {
+ return shortName;
+ }
+
+ public String getAuthor()
+ {
+ return author;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public Object clone() throws CloneNotSupportedException
+ {
+ return super.clone();
+ }
+}
\ No newline at end of file
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/connection/ClientConnection.java
@@ -0,0 +1,888 @@
+package com.stream_pi.server.connection;
+
+import com.stream_pi.actionapi.action.Action;
+import com.stream_pi.actionapi.action.ActionType;
+import com.stream_pi.actionapi.action.DisplayTextAlignment;
+import com.stream_pi.actionapi.action.Location;
+import com.stream_pi.actionapi.actionproperty.ClientProperties;
+import com.stream_pi.actionapi.actionproperty.property.Property;
+import com.stream_pi.actionapi.actionproperty.property.Type;
+import com.stream_pi.actionapi.normalaction.NormalAction;
+import com.stream_pi.server.action.NormalActionPlugins;
+import com.stream_pi.server.client.Client;
+import com.stream_pi.server.client.ClientProfile;
+import com.stream_pi.server.client.ClientTheme;
+import com.stream_pi.server.info.ServerInfo;
+import com.stream_pi.server.window.ExceptionAndAlertHandler;
+import com.stream_pi.util.alert.StreamPiAlert;
+import com.stream_pi.util.alert.StreamPiAlertType;
+import com.stream_pi.util.exception.MinorException;
+import com.stream_pi.util.exception.SevereException;
+import com.stream_pi.util.exception.StreamPiException;
+import com.stream_pi.util.platform.Platform;
+import com.stream_pi.util.platform.ReleaseStatus;
+import com.stream_pi.util.version.Version;
+import javafx.concurrent.Task;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.net.Socket;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class ClientConnection extends Thread{
+ private Socket socket;
+ private ServerListener serverListener;
+ private AtomicBoolean stop = new AtomicBoolean(false);
+
+ private DataInputStream dis;
+ private DataOutputStream dos;
+
+ private Logger logger;
+
+ private Client client = null;
+
+ private ExceptionAndAlertHandler exceptionAndAlertHandler;
+
+ public ClientConnection(Socket socket, ServerListener serverListener, ExceptionAndAlertHandler exceptionAndAlertHandler)
+ {
+ this.exceptionAndAlertHandler = exceptionAndAlertHandler;
+ //actionIconsToBeSent = new ArrayList__();
+ this.socket = socket;
+
+ this.serverListener = serverListener;
+
+ logger = Logger.getLogger(ClientConnection.class.getName());
+
+ try
+ {
+ dis = new DataInputStream(socket.getInputStream());
+ dos = new DataOutputStream(socket.getOutputStream());
+ } catch (IOException e) {
+ e.printStackTrace();
+
+ exceptionAndAlertHandler.handleMinorException(new MinorException("Unable to start socket streams"));
+ }
+
+ start();
+ }
+
+ public synchronized void exit()
+ {
+ if(stop.get())
+ return;
+
+ logger.info("Stopping ...");
+
+ try
+ {
+ if(socket !=null)
+ {
+ logger.info("Stopping connection "+socket.getRemoteSocketAddress());
+ disconnect();
+ }
+ }
+ catch (SevereException e)
+ {
+ e.printStackTrace();
+ exceptionAndAlertHandler.handleSevereException(e);
+ }
+ }
+
+ public synchronized void exitAndRemove()
+ {
+ exit();
+ removeConnection();
+ serverListener.clearTemp();
+ }
+
+ public void removeConnection()
+ {
+ ClientConnections.getInstance().removeConnection(this);
+ }
+
+
+ public void writeToStream(String text) throws SevereException
+ {
+ /*try
+ {
+ logger.debug(text);
+ dos.writeUTF(text);
+ dos.flush();
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ throw new SevereException("Unable to write to io Stream!");
+ }*/
+
+ try
+ {
+ byte[] txtBytes = text.getBytes();
+
+ Thread.sleep(50);
+ dos.writeUTF("string:: ::");
+ dos.flush();
+ dos.writeInt(txtBytes.length);
+ dos.flush();
+ write(txtBytes);
+ dos.flush();
+ }
+ catch (IOException | InterruptedException e)
+ {
+ e.printStackTrace();
+ throw new SevereException("Unable to write to io Stream!");
+ }
+
+ }
+
+ public void sendIcon(String profileID, String actionID, byte[] icon) throws SevereException
+ {
+ try
+ {
+ logger.info("Sending action Icon...");
+ //Thread.sleep(50);
+ System.out.println("1");
+ dos.writeUTF("action_icon::"+profileID+"!!"+actionID+"!!::"+icon.length);
+
+ System.out.println("2");
+ dos.flush();
+
+ System.out.println("3");
+ dos.writeInt(icon.length);
+
+ System.out.println("4");
+ dos.flush();
+
+ System.out.println("5");
+ write(icon);
+
+ System.out.println("6");
+ dos.flush();
+
+ System.out.println("7");
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ throw new SevereException("Unable to write to io Stream!");
+ }
+ }
+
+ public void write(byte[] array) throws SevereException
+ {
+ try
+ {
+ dos.write(array);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ throw new SevereException("Unable to write to io Stream!");
+ }
+ }
+
+
+ public void initAfterConnectionQueryReceive(String[] arr) throws StreamPiException
+ {
+ logger.info("Setting up client object ...");
+
+ Version clientVersion;
+ Version commsStandard;
+ Version themesStandard;
+
+ ReleaseStatus releaseStatus;
+
+ try
+ {
+ clientVersion = new Version(arr[1]);
+ releaseStatus = ReleaseStatus.valueOf(arr[2]);
+ commsStandard = new Version(arr[3]);
+ themesStandard = new Version(arr[4]);
+ }
+ catch (MinorException e)
+ {
+ exitAndRemove();
+ throw new MinorException(e.getShortMessage()+" (client '"+socket.getRemoteSocketAddress()+"' )");
+ }
+
+ if(!commsStandard.isEqual(ServerInfo.getInstance().getCommStandardVersion()))
+ {
+ String errTxt = "Server and client Communication standards do not match. Make sure you are on the latest version of server and client.\n" +
+ "Server Comms. Standard : "+ServerInfo.getInstance().getCommStandardVersion().getText()+
+ "\nclient Comms. Standard : "+commsStandard.getText();
+
+ disconnect(errTxt);
+ throw new MinorException(errTxt);
+ }
+
+ client = new Client(clientVersion, releaseStatus, commsStandard, themesStandard, arr[5], Platform.valueOf(arr[8]), socket.getRemoteSocketAddress());
+
+ client.setStartupDisplayWidth(Double.parseDouble(arr[6]));
+ client.setStartupDisplayHeight(Double.parseDouble(arr[7]));
+ client.setDefaultProfileID(arr[9]);
+ client.setDefaultThemeFullName(arr[10]);
+
+ //call get profiles command.
+ serverListener.clearTemp();
+ }
+
+ public synchronized Client getClient()
+ {
+ return client;
+ }
+
+ @Override
+ public void run() {
+
+ try {
+ initAfterConnectionQuerySend();
+ } catch (SevereException e) {
+ e.printStackTrace();
+
+ exceptionAndAlertHandler.handleSevereException(e);
+
+ exitAndRemove();
+ return;
+ }
+
+ try
+ {
+ while(!stop.get())
+ {
+ String msg = "";
+
+ try
+ {
+ String raw = dis.readUTF();
+
+ int length = dis.readInt();
+
+ System.out.println("SIZE TO READ : "+length);
+
+ String[] precursor = raw.split("::");
+
+ String inputType = precursor[0];
+ String secondArg = precursor[1];
+
+
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+
+ /*int count;
+ int chunkSize = 512;
+ while (length>0)
+ {
+ if(chunkSize > length)
+ chunkSize = length;
+ else
+ chunkSize = 512;
+
+ byte[] buffer = new byte[chunkSize];
+ count = dis.read(buffer);
+
+ System.out.println(count);
+
+ byteArrayOutputStream.write(buffer);
+
+ length-=count;
+ }*/
+
+ /*byte[] buffer = new byte[8192];
+ int read;
+ while((read = dis.read(buffer)) != -1){
+ System.out.println("READ : "+read);
+ byteArrayOutputStream.write(buffer, 0, read);
+ }
+
+ System.out.println("READ : "+byteArrayOutputStream.size());
+
+ byteArrayOutputStream.close();
+
+ byte[] bArr = byteArrayOutputStream.toByteArray();*/
+
+ byte[] bArr = new byte[length];
+
+ dis.readFully(bArr);
+
+ if(inputType.equals("string"))
+ {
+ msg = new String(bArr);
+ }
+ else if(inputType.equals("action_icon"))
+ {
+ String[] secondArgSep = secondArg.split("!!");
+
+ String profileID = secondArgSep[0];
+ String actionID = secondArgSep[1];
+
+ getClient().getProfileByID(profileID).getActionByID(actionID).setIcon(bArr);
+
+ //serverListener.clearTemp();
+ continue;
+ }
+ }
+ catch (IOException e)
+ {
+ logger.log(Level.SEVERE, e.getMessage());
+ e.printStackTrace();
+
+ serverListener.clearTemp();
+
+ if(!stop.get())
+ {
+ removeConnection();
+ throw new MinorException("Accidentally disconnected from "+getClient().getNickName()+".");
+ }
+
+ exitAndRemove();
+
+ return;
+ }
+
+ logger.info("Received text : '"+msg+"'");
+
+ String[] sep = msg.split("::");
+
+ String command = sep[0];
+
+ switch (command)
+ {
+ case "disconnect" : clientDisconnected(msg);
+ break;
+
+ case "client_details" : initAfterConnectionQueryReceive(sep);
+ getProfilesFromClient();
+ getThemesFromClient();
+ break;
+
+ case "profiles" : registerProfilesFromClient(sep);
+ break;
+
+ case "profile_details" : registerProfileDetailsFromClient(sep);
+ break;
+
+ case "action_details" : registerActionToProfile(sep);
+ break;
+
+ case "themes": registerThemes(sep);
+ break;
+
+ case "action_clicked": actionClicked(sep[1], sep[2]);
+ break;
+
+ default: logger.warning("Command '"+command+"' does not match records. Make sure client and server versions are equal.");
+
+
+ }
+ }
+ }
+ catch (StreamPiException e)
+ {
+ e.printStackTrace();
+
+
+ if(e instanceof MinorException)
+ exceptionAndAlertHandler.handleMinorException((MinorException) e);
+ else if (e instanceof SevereException)
+ exceptionAndAlertHandler.handleSevereException((SevereException) e);
+
+ }
+ }
+
+
+
+
+
+
+ // commands
+
+ public void initAfterConnectionQuerySend() throws SevereException
+ {
+ logger.info("Asking client details ...");
+ writeToStream("get_client_details::");
+ }
+
+ public void disconnect() throws SevereException {
+ disconnect("");
+ }
+
+ public void disconnect(String message) throws SevereException {
+ if(stop.get())
+ return;
+
+ stop.set(true);
+
+ logger.info("Sending client disconnect message ...");
+ writeToStream("disconnect::"+message+"::");
+
+
+ try
+ {
+ if(!socket.isClosed())
+ socket.close();
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ throw new SevereException("Unable to close socket");
+ }
+ }
+
+ public void clientDisconnected(String message)
+ {
+ stop.set(true);
+ String txt = "Disconnected!";
+
+ if(!message.equals("disconnect::::"))
+ txt = "Message : "+message.split("::")[1];
+
+ new StreamPiAlert("Disconnected from "+getClient().getNickName()+".", txt, StreamPiAlertType.WARNING).show();;
+ exitAndRemove();
+ }
+
+ public void getProfilesFromClient() throws StreamPiException
+ {
+ logger.info("Asking client to send profiles ...");
+ writeToStream("get_profiles::");
+ }
+
+ public void getThemesFromClient() throws StreamPiException
+ {
+ logger.info("Asking clients to send themes ...");
+ writeToStream("get_themes::");
+ }
+
+ public void registerThemes(String[] sep)
+ {
+ for(int i =1; i<sep.length;i++)
+ {
+ String[] internal = sep[i].split("__");
+
+ ClientTheme clientTheme = new ClientTheme(
+ internal[0],
+ internal[1],
+ internal[2],
+ internal[3]
+ );
+
+ try
+ {
+ getClient().addTheme(clientTheme);
+ }
+ catch (CloneNotSupportedException e)
+ {
+ logger.log(Level.SEVERE, e.getMessage());
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void registerProfilesFromClient(String[] sep) throws StreamPiException
+ {
+ logger.info("Registering profiles ...");
+
+ int noOfProfiles = Integer.parseInt(sep[1]);
+
+ for(int i = 2; i<(noOfProfiles + 2); i++)
+ {
+ String profileID = sep[i];
+ getProfileDetailsFromClient(profileID);
+ }
+ }
+
+ public void getProfileDetailsFromClient(String ID) throws StreamPiException
+ {
+ logger.info("Asking client to send details of profile : "+ID);
+ writeToStream("get_profile_details::"+ID+"::");
+ }
+
+
+ public void registerProfileDetailsFromClient(String[] sep)
+ {
+ String ID = sep[1];
+ logger.info("Registering details for profile : "+ID);
+
+ String name = sep[2];
+ int rows = Integer.parseInt(sep[3]);
+ int cols = Integer.parseInt(sep[4]);
+ int actionSize = Integer.parseInt(sep[5]);
+ int actionGap = Integer.parseInt(sep[6]);
+
+
+ ClientProfile clientProfile = new ClientProfile(name, ID, rows, cols, actionSize, actionGap);
+
+ logger.info("Added client profile "+clientProfile.getName());
+ try
+ {
+ getClient().addProfile(clientProfile);
+ }
+ catch (CloneNotSupportedException e)
+ {
+ logger.severe(e.getMessage());
+ e.printStackTrace();
+ }
+ serverListener.clearTemp();
+ }
+
+ /*public void getActionIcon(String profileID, String actionID) throws StreamPiException
+ {
+ System.out.println("getting action icon from "+profileID+", "+actionID);
+ writeToStream("get_action_icon::"+profileID+"::"+actionID);
+ }*/
+
+ public synchronized void registerActionToProfile(String[] sep) throws StreamPiException
+ {
+ String profileID = sep[1];
+
+ String ID = sep[2];
+ ActionType actionType = ActionType.valueOf(sep[3]);
+
+ //4 - Version
+ //5 - ModuleName
+
+ //display
+ String bgColorHex = sep[6];
+
+ //icon
+ boolean isHasIcon = sep[7].equals("true");
+ boolean isShowIcon = sep[8].equals("true");
+
+ //text
+ boolean isShowDisplayText = sep[9].equals("true");
+ String displayFontColor = sep[10];
+ String displayText = sep[11];
+ DisplayTextAlignment displayTextAlignment = DisplayTextAlignment.valueOf(sep[12]);
+
+ //location
+ String row = sep[13];
+ String col = sep[14];
+
+ Location location = new Location(Integer.parseInt(row), Integer.parseInt(col));
+
+
+
+ Action action = new Action(ID, actionType);
+
+ action.setBgColourHex(bgColorHex);
+ action.setShowIcon(isShowIcon);
+ action.setHasIcon(isHasIcon);
+
+ action.setShowDisplayText(isShowDisplayText);
+ action.setDisplayTextFontColourHex(displayFontColor);
+ action.setDisplayText(displayText);
+ action.setDisplayTextAlignment(displayTextAlignment);
+
+
+ action.setLocation(location);
+
+
+ //client properties
+
+ int clientPropertiesSize = Integer.parseInt(sep[15]);
+
+ String root = sep[17];
+ action.setParent(root);
+
+ String[] clientPropertiesRaw = sep[16].split("!!");
+
+ ClientProperties clientProperties = new ClientProperties();
+
+ if(actionType == ActionType.FOLDER)
+ clientProperties.setDuplicatePropertyAllowed(true);
+
+ for(int i = 0;i<clientPropertiesSize; i++)
+ {
+ String[] clientPraw = clientPropertiesRaw[i].split("__");
+
+ Property property = new Property(clientPraw[0], Type.STRING);
+
+ if(clientPraw.length > 1)
+ property.setRawValue(clientPraw[1]);
+
+ clientProperties.addProperty(property);
+ }
+
+ action.setClientProperties(clientProperties);
+ action.setModuleName(sep[5]);
+
+ //set up action
+
+ //action toBeAdded = null;
+
+ if(actionType == ActionType.NORMAL)
+ {
+ NormalAction actionCopy = NormalActionPlugins.getInstance().getPluginByModuleName(sep[5]);
+
+ if(actionCopy == null)
+ {
+ action.setInvalid(true);
+ }
+ else
+ {
+ action.setVersion(new Version(sep[4]));
+
+ //action.setHelpLink(actionCopy.getHelpLink());
+
+ if(actionCopy.getVersion().getMajor() != action.getVersion().getMajor())
+ {
+ action.setInvalid(true);
+ }
+ else
+ {
+ action.setName(actionCopy.getName());
+
+ ClientProperties finalClientProperties = new ClientProperties();
+
+
+ for(Property property : actionCopy.getClientProperties().get())
+ {
+ for(int i = 0;i<action.getClientProperties().getSize();i++)
+ {
+ Property property1 = action.getClientProperties().get().get(i);
+ if (property.getName().equals(property1.getName()))
+ {
+ property.setRawValue(property1.getRawValue());
+
+
+ finalClientProperties.addProperty(property);
+ }
+ }
+ }
+
+ action.setClientProperties(finalClientProperties);
+
+ }
+ }
+ }
+
+
+ try
+ {
+ for(Property prop : action.getClientProperties().get())
+ {
+ logger.info("G@@@@@ : "+prop.getRawValue());
+ }
+
+
+ getClient().getProfileByID(profileID).addAction(action);
+
+
+
+ for(String action1x : getClient().getProfileByID(profileID).getActionsKeySet())
+ {
+ Action action1 = getClient().getProfileByID(profileID).getActionByID(action1x);
+ logger.info("231cc : "+action1.getID());
+ for(Property prop : action1.getClientProperties().get())
+ {
+ logger.info("G@VVVV@@@ : "+prop.getRawValue());
+ }
+ }
+
+ }
+ catch (CloneNotSupportedException e)
+ {
+ e.printStackTrace();
+ exceptionAndAlertHandler.handleMinorException(new MinorException("action", "Unable to clone"));
+ }
+
+ }
+
+ public void saveActionDetails(String profileID, Action action) throws SevereException
+ {
+ StringBuilder finalQuery = new StringBuilder("save_action_details::");
+
+
+ //failsafes
+
+ if(action.getDisplayText().endsWith(":"))
+ action.setDisplayText(action.getDisplayText()+" ");
+
+
+ finalQuery.append(profileID)
+ .append("::")
+ .append(action.getID())
+ .append("::")
+ .append(action.getActionType())
+ .append("::");
+
+ if(action.getActionType() == ActionType.NORMAL)
+ {
+ finalQuery.append(action.getVersion().getText());
+ System.out.println("VERSION :sdd "+action.getVersion().getText());
+ }
+
+ finalQuery.append("::");
+
+ if(action.getActionType() == ActionType.NORMAL)
+ finalQuery.append(action.getModuleName());
+
+ finalQuery.append("::");
+
+ //display
+
+ finalQuery.append(action.getBgColourHex())
+ .append("::");
+
+ //icon
+ finalQuery.append(action.isHasIcon())
+ .append("::")
+ .append(action.isShowIcon())
+ .append("::");
+
+ //text
+ finalQuery.append(action.isShowDisplayText())
+ .append("::")
+ .append(action.getDisplayTextFontColourHex())
+ .append("::")
+ .append(action.getDisplayText())
+ .append("::")
+ .append(action.getDisplayTextAlignment())
+ .append("::");
+
+ //location
+
+ if(action.getLocation() == null)
+ finalQuery.append("-1::-1::");
+ else
+ finalQuery.append(action.getLocation().getRow())
+ .append("::")
+ .append(action.getLocation().getCol())
+ .append("::");
+
+ //client properties
+
+ ClientProperties clientProperties = action.getClientProperties();
+
+ finalQuery.append(clientProperties.getSize())
+ .append("::");
+
+ for(Property property : clientProperties.get())
+ {
+ finalQuery.append(property.getName())
+ .append("__")
+ .append(property.getRawValue())
+ .append("__");
+
+ finalQuery.append("!!");
+ }
+
+ finalQuery.append("::")
+ .append(action.getParent())
+ .append("::");
+
+ writeToStream(finalQuery.toString());
+
+ }
+
+ public void deleteAction(String profileID, String actionID) throws SevereException
+ {
+ writeToStream("delete_action::"+profileID+"::"+actionID);
+ }
+
+ public void saveClientDetails(String clientNickname, String screenWidth, String screenHeight, String defaultProfileID,
+ String defaultThemeFullName) throws SevereException
+ {
+ writeToStream("save_client_details::"+
+ clientNickname+"::"+
+ screenWidth+"::"+
+ screenHeight+"::"+
+ defaultProfileID+"::"+
+ defaultThemeFullName+"::");
+
+ client.setNickName(clientNickname);
+ client.setStartupDisplayWidth(Double.parseDouble(screenWidth));
+ client.setStartupDisplayHeight(Double.parseDouble(screenHeight));
+ client.setDefaultProfileID(defaultProfileID);
+ client.setDefaultThemeFullName(defaultThemeFullName);
+ }
+
+ public void saveProfileDetails(ClientProfile clientProfile) throws SevereException, CloneNotSupportedException {
+ if(client.getProfileByID(clientProfile.getID()) !=null)
+ {
+ client.getProfileByID(clientProfile.getID()).setName(clientProfile.getName());
+ client.getProfileByID(clientProfile.getID()).setRows(clientProfile.getRows());
+ client.getProfileByID(clientProfile.getID()).setCols(clientProfile.getCols());
+ client.getProfileByID(clientProfile.getID()).setActionSize(clientProfile.getActionSize());
+ client.getProfileByID(clientProfile.getID()).setActionGap(clientProfile.getActionGap());
+ }
+ else
+ client.addProfile(clientProfile);
+
+ writeToStream("save_client_profile::"+
+ clientProfile.getID()+"::"+
+ clientProfile.getName()+"::"+
+ clientProfile.getRows()+"::"+
+ clientProfile.getCols()+"::"+
+ clientProfile.getActionSize()+"::"+
+ clientProfile.getActionGap()+"::");
+ }
+
+ public void deleteProfile(String ID) throws SevereException
+ {
+ writeToStream("delete_profile::"+ID+"::");
+ }
+
+ public void actionClicked(String profileID, String actionID) {
+
+ try
+ {
+ Action action = client.getProfileByID(profileID).getActionByID(actionID);
+
+ if(action.getActionType() == ActionType.NORMAL)
+ {
+ NormalAction original = NormalActionPlugins.getInstance().getPluginByModuleName(
+ action.getModuleName()
+ );
+
+ if(original == null)
+ {
+ throw new MinorException(
+ "The action isn't installed on the server."
+ );
+ }
+
+ NormalAction normalAction = original.clone();
+
+
+
+ normalAction.setLocation(action.getLocation());
+ normalAction.setDisplayText(action.getDisplayText());
+ normalAction.setID(actionID);
+
+ normalAction.setClientProperties(action.getClientProperties());
+
+ new Thread(new Task<Void>() {
+ @Override
+ protected Void call()
+ {
+ try
+ {
+ boolean result = serverListener.onNormalActionClicked(normalAction);
+ if(!result)
+ {
+ sendActionFailed(profileID, actionID);
+ }
+ }
+ catch (SevereException e)
+ {
+ exceptionAndAlertHandler.handleSevereException(e);
+ }
+ return null;
+ }
+ }).start();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ exceptionAndAlertHandler.handleMinorException(new MinorException(e.getMessage()));
+ }
+ }
+
+ public void sendActionFailed(String profileID, String actionID) throws SevereException {
+ logger.info("Sending failed status ...");
+ writeToStream("action_failed::"+
+ profileID+"::"+
+ actionID+"::");
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/connection/ClientConnections.java
@@ -0,0 +1,70 @@
+package com.stream_pi.server.connection;
+
+
+import java.net.SocketAddress;
+import java.util.ArrayList;
+
+public class ClientConnections {
+
+ private ArrayList<ClientConnection> connections;
+
+ private static ClientConnections instance = null;
+
+ private ClientConnections()
+ {
+ connections = new ArrayList<>();
+ }
+
+ public static synchronized ClientConnections getInstance()
+ {
+ if(instance == null)
+ {
+ instance = new ClientConnections();
+ }
+
+ return instance;
+ }
+
+ public ArrayList<ClientConnection> getConnections()
+ {
+ return connections;
+ }
+
+ public void clearAllConnections()
+ {
+ connections.clear(); // NOT RECOMMENDED TO USE CARELESSLY
+ }
+
+ public void addConnection(ClientConnection connection)
+ {
+ connections.add(connection);
+ }
+
+ public void removeConnection(ClientConnection clientConnection)
+ {
+ System.out.println(connections.remove(clientConnection)+" 22222222222222222222222222222222222222222");
+ }
+
+ public void disconnectAll()
+ {
+ new Thread(()->{
+ for(ClientConnection clientConnection : connections)
+ {
+ clientConnection.exit();
+ }
+
+ clearAllConnections();
+ }).start();
+ }
+
+ public ClientConnection getClientConnectionBySocketAddress(SocketAddress socketAddress)
+ {
+ for(ClientConnection clientConnection : connections)
+ {
+ if(clientConnection.getClient().getRemoteSocketAddress().equals(socketAddress))
+ return clientConnection;
+ }
+
+ return null;
+ }
+}
\ No newline at end of file
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/connection/ConnectionService.java
@@ -0,0 +1,345 @@
+/*package com.StreamPi.Server.connection;
+
+import com.StreamPi.ActionAPI.action.action;
+import com.StreamPi.ActionAPI.action.ActionType;
+import com.StreamPi.ActionAPI.action.Location;
+import com.StreamPi.ActionAPI.ActionProperty.ClientProperties;
+import com.StreamPi.ActionAPI.NormalAction.NormalAction;
+import com.StreamPi.CommAPI.ConnectionGrpc;
+import com.StreamPi.CommAPI.ServerGRPC;
+import NormalActionPlugins;
+import client;
+import ClientProfile;
+import ServerInfo;
+import com.StreamPi.Util.Exception.MinorException;
+import com.StreamPi.Util.Exception.SevereException;
+import com.StreamPi.Util.Exception.StreamPiException;
+import com.StreamPi.Util.Platform.Platform;
+import com.StreamPi.Util.Version.Version;
+import io.grpc.stub.StreamObserver;
+import javafx.concurrent.Task;
+import javafx.scene.control.Alert;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+public class ConnectionService extends ConnectionGrpc.ConnectionImplBase {
+
+ private client client = null;
+ private Logger logger;
+
+ ServerListener serverListener;
+
+ final HashMap<String, Boolean> actionStatuses;
+
+ public ConnectionService(ServerListener serverListener)
+ {
+ super();
+
+ isDisconnect = false;
+ disconnectMessage = "";
+
+ logger = LoggerFactory.getLogger(ConnectionService.class);
+ actionStatuses = new HashMap<>();
+
+ this.serverListener = serverListener;
+ }
+
+
+ boolean isDisconnect;
+ String disconnectMessage;
+
+ public void disconnect()
+ {
+ disconnect("");
+ }
+
+ public void disconnect(String message)
+ {
+ if(!isDisconnect)
+ {
+ this.isDisconnect = true;
+ this.disconnectMessage = message;
+ }
+ }
+
+ @Override
+ public void sendClientDetails(ServerGRPC.ClientDetails request, StreamObserver<ServerGRPC.Status> responseObserver) {
+
+ Version clientVersion;
+ Version commsAPIVersion;
+ Version themeAPIVersion;
+
+ try
+ {
+ clientVersion = new Version(request.getClientVersion());
+ commsAPIVersion = new Version(request.getCommAPIVersion());
+ themeAPIVersion = new Version(request.getThemeAPIVersion());
+ }
+ catch (MinorException e)
+ {
+ e.printStackTrace();
+ serverListener.onRPCError(new MinorException("versions invalid. Check stacktrace"));
+ disconnect();
+ return;
+ }
+
+
+ String nickName = request.getNickName();
+ Platform platform = Platform.valueOf(request.getPlatform().toString());
+
+ client = new client(clientVersion, commsAPIVersion, themeAPIVersion, nickName, platform, null);
+
+ boolean sendActions = true;
+
+ if(!commsAPIVersion.isEqual(ServerInfo.getInstance().getCommAPIVersion()))
+ {
+ sendActions = false;
+ disconnect("client CommAPI and Server CommAPI do not match!");
+ }
+
+ responseObserver.onNext(ServerGRPC.Status.newBuilder().setSendActions(sendActions).build());
+
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public StreamObserver<ServerGRPC.ClientProfile> sendClientProfiles(StreamObserver<ServerGRPC.Empty> responseObserver) {
+
+ client.getProfiles().clear();
+
+ ArrayList<String> notFoundActions = new ArrayList<>();
+
+ return new StreamObserver<ServerGRPC.ClientProfile>() {
+ @Override
+ public void onNext(ServerGRPC.ClientProfile clientProfile) {
+
+ String name = clientProfile.getName();
+ String id = clientProfile.getId();
+
+ int rows = clientProfile.getRows();
+ int cols = clientProfile.getCols();
+
+ int actionSize = clientProfile.getActionSize();
+ int actionGap = clientProfile.getActionGap();
+
+ ClientProfile finalClientProfile = new ClientProfile(name, id, rows, cols, actionSize, actionGap);
+
+ ArrayList<action> actions = new ArrayList<>();
+
+ List<ServerGRPC.ClientAction> clientActions = clientProfile.getActionsList();
+ for(ServerGRPC.ClientAction clientAction : clientActions)
+ {
+
+ String actionID = clientAction.getId();
+ String actionName = clientAction.getActionName();
+
+ boolean hasIcon = clientAction.getHasIcon();
+
+ ActionType actionType = ActionType.valueOf(clientAction.getActionType().toString());
+
+ action action = new action(actionID, actionType);
+ action.setActionName(actionName);
+
+ action.setHasIcon(hasIcon);
+
+ int locationX = clientAction.getLocationX();
+ int locationY = clientAction.getLocationY();
+
+ action.setLocation(new Location(locationX, locationY));
+
+ if(actionType == ActionType.NORMAL)
+ {
+ action.setModuleName(clientAction.getModuleName());
+
+ ClientProperties properties = new ClientProperties();
+
+ List<ServerGRPC.ClientProperty> clientProperties = clientAction.getClientPropertiesList();
+
+ for(ServerGRPC.ClientProperty clientProperty : clientProperties)
+ {
+ String propertyName = clientProperty.getName();
+ String propertyValue = clientProperty.getValue();
+
+ properties.addProperty(propertyName, propertyValue);
+ }
+
+ action.setClientProperties(properties);
+
+ boolean isFound = false;
+ for(NormalAction normalAction : NormalActionPlugins.getInstance().getPlugins())
+ {
+ if(normalAction.getModuleName().equals(action.getModuleName()))
+ {
+ isFound = true;
+
+ normalAction.setClientProperties(action.getClientProperties());
+ normalAction.setActionName(action.getActionName());
+ normalAction.setHasIcon(action.isHasIcon());
+ normalAction.setID(action.getID());
+ normalAction.setLocation(action.getLocation());
+ normalAction.setInvalid(false);
+
+ actions.add(normalAction);
+
+ break;
+ }
+ }
+
+ if(!isFound)
+ {
+ String aName = action.getModuleName();
+
+ action.setInvalid(true);
+
+ logger.warn("action "+aName+" not found!");
+ if(!notFoundActions.contains(aName))
+ notFoundActions.add(aName);
+
+ actions.add(action);
+ }
+ }
+ }
+
+ finalClientProfile.setActions(actions);
+ client.addProfile(finalClientProfile);
+
+
+ }
+
+ @Override
+ public void onError(Throwable throwable) {
+ serverListener.onRPCError(new SevereException(throwable.getMessage()));
+ }
+
+ @Override
+ public void onCompleted() {
+
+ if(!notFoundActions.isEmpty())
+ {
+ StringBuilder all = new StringBuilder("Some actions cannot be edited/used because they are not installed on the server : ");
+
+ for(String each : notFoundActions)
+ {
+ all.append("\n * ").append(each);
+ }
+
+ serverListener.onAlert("Warning",all.toString(), Alert.AlertType.WARNING);
+ }
+
+ responseObserver.onNext(ServerGRPC.Empty.newBuilder().build());
+ responseObserver.onCompleted();
+ }
+ };
+ }
+
+ @Override
+ public void actionClicked(ServerGRPC.ClickedActionID request, StreamObserver<ServerGRPC.Empty> responseObserver) {
+ try
+ {
+ action actionClicked = client.getProfileByID(request.getProfileID()).getActionByID(request.getId());
+ new Thread(new Task<Void>() {
+ @Override
+ protected Void call()
+ {
+ try
+ {
+ synchronized (actionStatuses)
+ {
+ actionStatuses.put(request.getId(), serverListener.onActionClicked(actionClicked));
+ }
+ }
+ catch (MinorException e)
+ {
+ serverListener.onRPCError(e);
+ }
+ return null;
+ }
+ }).start();
+ }
+ catch (MinorException e)
+ {
+ e.printStackTrace();
+ }
+ finally {
+ responseObserver.onNext(ServerGRPC.Empty.newBuilder().build());
+ responseObserver.onCompleted();
+ }
+ }
+
+ @Override
+ public StreamObserver<ServerGRPC.Empty> actionClickedStatus(StreamObserver<ServerGRPC.ActionStatus> responseObserver) {
+ return new StreamObserver<ServerGRPC.Empty>() {
+ @Override
+ public void onNext(ServerGRPC.Empty empty) {
+
+ }
+
+ @Override
+ public void onError(Throwable throwable) {
+ serverListener.onRPCError(new StreamPiException(throwable.getMessage()));
+ }
+
+ @Override
+ public void onCompleted() {
+ String id = null;
+ boolean success = false;
+ synchronized (actionStatuses)
+ {
+ if(!actionStatuses.isEmpty())
+ {
+ for(String key : actionStatuses.keySet())
+ {
+ id = key;
+ success = actionStatuses.get(id);
+
+ System.out.println("SDSDSDASDASDXZXCZXCZXC");
+ break;
+ }
+ }
+ }
+
+ if(id==null)
+ {
+ responseObserver.onNext(ServerGRPC.ActionStatus.newBuilder().build());
+ }
+ else
+ responseObserver.onNext(ServerGRPC.ActionStatus.newBuilder()
+ .setId(id)
+ .setIsSuccess(success)
+ .build());
+
+ responseObserver.onCompleted();
+ }
+ };
+ }
+
+ @Override
+ public StreamObserver<ServerGRPC.DisconnectMessage> disconnect(StreamObserver<ServerGRPC.DisconnectMessage> responseObserver) {
+ return new StreamObserver<ServerGRPC.DisconnectMessage>() {
+ @Override
+ public void onNext(ServerGRPC.DisconnectMessage disconnectMessage) {
+ if(disconnectMessage.getIsDisconnect())
+ disconnect(disconnectMessage.getMessage());
+ }
+
+ @Override
+ public void onError(Throwable throwable) {
+ serverListener.onRPCError(new StreamPiException(throwable.getMessage()));
+ }
+
+ @Override
+ public void onCompleted() {
+ responseObserver.onNext(ServerGRPC.DisconnectMessage.newBuilder()
+ .setIsDisconnect(isDisconnect)
+ .setMessage(disconnectMessage)
+ .build());
+ responseObserver.onCompleted();
+ }
+ };
+ }
+}
+*/
\ No newline at end of file
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/connection/MainServer.java
@@ -0,0 +1,104 @@
+package com.stream_pi.server.connection;
+
+import com.stream_pi.server.window.ExceptionAndAlertHandler;
+import com.stream_pi.util.exception.MinorException;
+import com.stream_pi.util.exception.SevereException;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.logging.Logger;
+
+public class MainServer extends Thread{
+ private ServerListener serverListener;
+
+ private Logger logger = Logger.getLogger(MainServer.class.getName());
+ private int port;
+ private ServerSocket serverSocket = null;
+ //private Server server;
+
+
+ private AtomicBoolean stop = new AtomicBoolean(false);
+
+ private ExceptionAndAlertHandler exceptionAndAlertHandler;
+ public MainServer(ServerListener serverListener, ExceptionAndAlertHandler exceptionAndAlertHandler)
+ {
+ this.exceptionAndAlertHandler = exceptionAndAlertHandler;
+ this.port = port;
+ this.serverListener = serverListener;
+ }
+
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ @Override
+ public synchronized void start() {
+ stop.set(false);
+ super.start();
+ }
+
+ public void stopListeningForConnections()
+ {
+
+ /*if(server !=null)
+ {
+ if(!server.isShutdown())
+ server.shutdown();
+ }*/
+
+ try
+ {
+ logger.info("Stopping listening for connections ...");
+ if(serverSocket!=null)
+ if(!serverSocket.isClosed())
+ serverSocket.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ finally {
+ logger.info("... Done!");
+ }
+ stop.set(true);
+ }
+
+ @Override
+ public void run() {
+ logger.warning("Starting main server on port "+port+" ...");
+
+ try {
+
+ logger.info("Starting server on port "+port+" ...");
+ /*Server server = ServerBuilder.forPort(port)
+ .addService(new ConnectionService(serverListener))
+ .build();
+
+ server.start();
+ logger.info("... Done!");*/
+
+ serverSocket = new ServerSocket(port);
+
+ while(!stop.get())
+ {
+ Socket s = serverSocket.accept();
+ ClientConnections.getInstance().addConnection(new ClientConnection(s, serverListener, exceptionAndAlertHandler));
+
+ logger.info("New client connected ("+s.getRemoteSocketAddress()+") !");
+ }
+
+ }
+ catch (SocketException e)
+ {
+ logger.info("Main Server stopped accepting calls ...");
+ e.printStackTrace(); //more likely stopped listening;
+ } catch (IOException e) {
+ exceptionAndAlertHandler.handleSevereException(new SevereException("MainServer io Exception occurred!"));
+ e.printStackTrace();
+ }
+ }
+
+
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/connection/ServerListener.java
@@ -0,0 +1,13 @@
+package com.stream_pi.server.connection;
+
+import com.stream_pi.actionapi.normalaction.NormalAction;
+
+public interface ServerListener {
+ boolean onNormalActionClicked(NormalAction action);
+
+ void clearTemp();
+
+ void init();
+
+ void othInit();
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/controller/Controller.java
@@ -0,0 +1,540 @@
+package com.stream_pi.server.controller;
+
+import com.stream_pi.actionapi.action.ServerConnection;
+import com.stream_pi.actionapi.action.PropertySaver;
+import com.stream_pi.actionapi.normalaction.NormalAction;
+import com.stream_pi.server.Main;
+import com.stream_pi.server.action.NormalActionPlugins;
+import com.stream_pi.server.connection.ClientConnections;
+import com.stream_pi.server.connection.MainServer;
+import com.stream_pi.server.io.Config;
+import com.stream_pi.server.info.ServerInfo;
+import com.stream_pi.server.window.Base;
+import com.stream_pi.server.window.dashboard.DonatePopupContent;
+import com.stream_pi.server.window.firsttimeuse.FirstTimeUse;
+import com.stream_pi.util.alert.StreamPiAlert;
+import com.stream_pi.util.alert.StreamPiAlertListener;
+import com.stream_pi.util.alert.StreamPiAlertType;
+import com.stream_pi.util.exception.MinorException;
+import com.stream_pi.util.exception.SevereException;
+import com.stream_pi.util.iohelper.IOHelper;
+
+import javafx.animation.Interpolator;
+import javafx.animation.KeyFrame;
+import javafx.animation.KeyValue;
+import javafx.animation.Timeline;
+import javafx.application.Platform;
+import javafx.concurrent.Task;
+import javafx.scene.Node;
+import javafx.scene.Scene;
+import javafx.stage.Modality;
+import javafx.stage.Stage;
+import javafx.stage.WindowEvent;
+import java.awt.SystemTray;
+import javafx.util.Duration;
+import java.awt.Toolkit;
+import java.awt.TrayIcon;
+import java.awt.PopupMenu;
+import java.awt.MenuItem;
+
+import java.io.File;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Random;
+import java.util.logging.Level;
+
+public class Controller extends Base implements PropertySaver, ServerConnection
+{
+ MainServer mainServer;
+
+ final SystemTray systemTray;
+
+ public void setupDashWindow() throws SevereException
+ {
+ try
+ {
+ getStage().setTitle("Stream-Pi Server - "+InetAddress.getLocalHost().getCanonicalHostName()+":"+ Config.getInstance().getPort()); //Sets title
+ getStage().setOnCloseRequest(this::onCloseRequest);
+ }
+ catch (UnknownHostException e)
+ {
+ e.printStackTrace();
+ throw new SevereException(e.getMessage());
+ }
+ }
+
+ private void checkPrePathDirectory() throws SevereException
+ {
+ try {
+ File filex = new File(ServerInfo.getInstance().getPrePath());
+
+ System.out.println("SAX : "+filex.exists());
+ if(!filex.exists())
+ {
+ filex.mkdirs();
+ IOHelper.unzip(Main.class.getResourceAsStream("Default.obj"), ServerInfo.getInstance().getPrePath());
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ throw new SevereException(e.getMessage());
+ }
+ }
+
+ @Override
+ public void init()
+ {
+ try {
+ checkPrePathDirectory();
+
+ initBase();
+ setupDashWindow();
+
+
+ setupSettingsWindowsAnimations();
+
+ NormalActionPlugins.getInstance().setPropertySaver(this);
+ NormalActionPlugins.getInstance().setServerConnection(this);
+
+
+ getDashboardPane().getPluginsPane().getSettingsButton().setOnAction(event -> {
+ openSettingsTimeLine.play();
+ });
+
+ getSettingsPane().getCloseButton().setOnAction(event -> {
+ closeSettingsTimeLine.play();
+ });
+
+ getSettingsPane().getThemesSettings().setController(this);
+
+
+ mainServer = new MainServer(this, this);
+
+
+ if(getConfig().isFirstTimeUse())
+ {
+ Stage stage = new Stage();
+ Scene s = new Scene(new FirstTimeUse(this, this), 512, 300);
+ stage.setResizable(false);
+ stage.setScene(s);
+ stage.setTitle("Stream-Pi Server Setup");
+ stage.initModality(Modality.APPLICATION_MODAL);
+ stage.setOnCloseRequest(event->Platform.exit());
+ stage.show();
+ }
+ else
+ {
+ if(getConfig().isAllowDonatePopup())
+ {
+ if(new Random().nextInt(5) == 3)
+ new DonatePopupContent(getHostServices(), this).show();
+ }
+
+ othInit();
+ }
+
+ }
+ catch (SevereException e)
+ {
+ handleSevereException(e);
+ }
+ }
+
+ @Override
+ public void othInit()
+ {
+ try
+ {
+ if(ServerInfo.getInstance().isStartMinimised())
+ minimiseApp();
+ else
+ getStage().show();
+ }
+ catch(MinorException e)
+ {
+ handleMinorException(e);
+ }
+
+ new Thread(new Task<Void>() {
+ @Override
+ protected Void call()
+ {
+ try
+ {
+ getSettingsPane().getGeneralSettings().loadDataFromConfig();
+
+ //themes
+ getSettingsPane().getThemesSettings().setThemes(getThemes());
+ getSettingsPane().getThemesSettings().setCurrentThemeFullName(getCurrentTheme().getFullName());
+ getSettingsPane().getThemesSettings().loadThemes();
+
+ //clients
+ getSettingsPane().getClientsSettings().loadData();
+
+ try
+ {
+
+ //Plugins
+ Platform.runLater(()->{
+ getDashboardPane().getPluginsPane().clearData();
+ getDashboardPane().getPluginsPane().loadOtherActions();
+ });
+
+ NormalActionPlugins.setPluginsLocation(getConfig().getPluginsPath());
+ NormalActionPlugins.getInstance().init();
+
+ Platform.runLater(()->getDashboardPane().getPluginsPane().loadData());
+
+ getSettingsPane().getPluginsSettings().loadPlugins();
+ }
+ catch (MinorException e)
+ {
+ getSettingsPane().getPluginsSettings().showPluginInitError();
+ handleMinorException(e);
+ }
+
+ //Server
+ mainServer.setPort(getConfig().getPort());
+ mainServer.start();
+
+ }
+ catch (SevereException e)
+ {
+ handleSevereException(e);
+ }
+ return null;
+ }
+ }).start();
+ }
+
+ private void setupSettingsWindowsAnimations()
+ {
+ Node settingsNode = getSettingsPane();
+ Node dashboardNode = getDashboardPane();
+
+ openSettingsTimeLine = new Timeline();
+ openSettingsTimeLine.setCycleCount(1);
+
+
+ openSettingsTimeLine.getKeyFrames().addAll(
+ new KeyFrame(Duration.millis(0.0D),
+ new KeyValue(settingsNode.opacityProperty(),
+ 0.0D, Interpolator.EASE_IN),
+ new KeyValue(settingsNode.scaleXProperty(),
+ 1.1D, Interpolator.EASE_IN),
+ new KeyValue(settingsNode.scaleYProperty(),
+ 1.1D, Interpolator.EASE_IN),
+ new KeyValue(settingsNode.scaleZProperty(),
+ 1.1D, Interpolator.EASE_IN)),
+ new KeyFrame(Duration.millis(90.0D),
+ new KeyValue(settingsNode.opacityProperty(),
+ 1.0D, Interpolator.LINEAR),
+ new KeyValue(settingsNode.scaleXProperty(),
+ 1.0D, Interpolator.LINEAR),
+ new KeyValue(settingsNode.scaleYProperty(),
+ 1.0D, Interpolator.LINEAR),
+ new KeyValue(settingsNode.scaleZProperty(),
+ 1.0D, Interpolator.LINEAR)),
+
+
+ new KeyFrame(Duration.millis(0.0D),
+ new KeyValue(dashboardNode.opacityProperty(),
+ 1.0D, Interpolator.LINEAR),
+ new KeyValue(dashboardNode.scaleXProperty(),
+ 1.0D, Interpolator.LINEAR),
+ new KeyValue(dashboardNode.scaleYProperty(),
+ 1.0D, Interpolator.LINEAR),
+ new KeyValue(dashboardNode.scaleZProperty(),
+ 1.0D, Interpolator.LINEAR)),
+ new KeyFrame(Duration.millis(90.0D),
+ new KeyValue(dashboardNode.opacityProperty(),
+ 0.0D, Interpolator.LINEAR),
+ new KeyValue(dashboardNode.scaleXProperty(),
+ 0.9D, Interpolator.LINEAR),
+ new KeyValue(dashboardNode.scaleYProperty(),
+ 0.9D, Interpolator.LINEAR),
+ new KeyValue(dashboardNode.scaleZProperty(),
+ 0.9D, Interpolator.LINEAR))
+ );
+
+ openSettingsTimeLine.setOnFinished(event1 -> {
+ settingsNode.toFront();
+ });
+
+
+ closeSettingsTimeLine = new Timeline();
+ closeSettingsTimeLine.setCycleCount(1);
+
+ closeSettingsTimeLine.getKeyFrames().addAll(
+
+ new KeyFrame(Duration.millis(0.0D),
+ new KeyValue(settingsNode.opacityProperty(),
+ 1.0D, Interpolator.LINEAR),
+ new KeyValue(settingsNode.scaleXProperty(),
+ 1.0D, Interpolator.LINEAR),
+ new KeyValue(settingsNode.scaleYProperty(),
+ 1.0D, Interpolator.LINEAR),
+ new KeyValue(settingsNode.scaleZProperty(),
+ 1.0D, Interpolator.LINEAR)),
+ new KeyFrame(Duration.millis(90.0D),
+ new KeyValue(settingsNode.opacityProperty(),
+ 0.0D, Interpolator.LINEAR),
+ new KeyValue(settingsNode.scaleXProperty(),
+ 1.1D, Interpolator.LINEAR),
+ new KeyValue(settingsNode.scaleYProperty(),
+ 1.1D, Interpolator.LINEAR),
+ new KeyValue(settingsNode.scaleZProperty(),
+ 1.1D, Interpolator.LINEAR)),
+
+ new KeyFrame(Duration.millis(0.0D),
+ new KeyValue(dashboardNode.opacityProperty(),
+ 0.0D, Interpolator.LINEAR),
+ new KeyValue(dashboardNode.scaleXProperty(),
+ 0.9D, Interpolator.LINEAR),
+ new KeyValue(dashboardNode.scaleYProperty(),
+ 0.9D, Interpolator.LINEAR),
+ new KeyValue(dashboardNode.scaleZProperty(),
+ 0.9D, Interpolator.LINEAR)),
+ new KeyFrame(Duration.millis(90.0D),
+ new KeyValue(dashboardNode.opacityProperty(),
+ 1.0D, Interpolator.LINEAR),
+ new KeyValue(dashboardNode.scaleXProperty(),
+ 1.0D, Interpolator.LINEAR),
+ new KeyValue(dashboardNode.scaleYProperty(),
+ 1.0D, Interpolator.LINEAR),
+ new KeyValue(dashboardNode.scaleZProperty(),
+ 1.0D, Interpolator.LINEAR))
+
+ );
+
+ closeSettingsTimeLine.setOnFinished(event1 -> {
+ dashboardNode.toFront();
+ new Thread(new Task<Void>() {
+ @Override
+ protected Void call() {
+ try {
+ getSettingsPane().getClientsSettings().loadData();
+
+ getSettingsPane().getGeneralSettings().loadDataFromConfig();
+ getSettingsPane().getPluginsSettings().loadPlugins();
+
+ getSettingsPane().getThemesSettings().setThemes(getThemes());
+ getSettingsPane().getThemesSettings().setCurrentThemeFullName(getCurrentTheme().getFullName());
+ getSettingsPane().getThemesSettings().loadThemes();
+
+ getSettingsPane().setDefaultTabToGeneral();
+ }
+ catch (SevereException e)
+ {
+ handleSevereException(e);
+ }
+ catch (MinorException e)
+ {
+ handleMinorException(e);
+ }
+ return null;
+ }
+ }).start();
+ });
+ }
+
+ private Timeline openSettingsTimeLine;
+ private Timeline closeSettingsTimeLine;
+
+
+ public Controller(){
+ systemTray = SystemTray.getSystemTray();
+ mainServer = null;
+ }
+
+ public void onCloseRequest(WindowEvent event)
+ {
+ try
+ {
+ if(Config.getInstance().getCloseOnX())
+ {
+ getConfig().setStartupWindowSize(
+ getWidth(),
+ getHeight()
+ );
+ getConfig().save();
+ onQuitApp();
+ NormalActionPlugins.getInstance().shutDownActions();
+ Platform.exit();
+ }
+ else
+ {
+ minimiseApp();
+ event.consume();
+ }
+ }
+ catch (SevereException e)
+ {
+ handleSevereException(e);
+ }
+ catch (MinorException e)
+ {
+ handleMinorException(e);
+ }
+ finally
+ {
+ closeLogger();
+ }
+ }
+
+ public void onQuitApp()
+ {
+ if(mainServer!=null)
+ mainServer.stopListeningForConnections();
+
+ ClientConnections.getInstance().disconnectAll();
+
+ getLogger().info("Shutting down ...");
+ }
+
+ public void minimiseApp() throws MinorException
+ {
+ try
+ {
+
+ if(SystemTray.isSupported())
+ {
+ if(getTrayIcon() == null)
+ initIconTray();
+
+ systemTray.add(getTrayIcon());
+ //getStage().setIconified(true);
+ getStage().hide();
+ }
+ else
+ {
+ new StreamPiAlert("System Tray Error", "Your System does not support System Tray", StreamPiAlertType.ERROR).show();
+ }
+ }
+ catch(Exception e)
+ {
+ throw new MinorException(e.getMessage());
+ }
+ }
+
+ public void initIconTray()
+ {
+
+ Platform.setImplicitExit(false);
+
+ PopupMenu popup = new PopupMenu();
+
+ MenuItem showItem = new MenuItem("Show");
+ showItem.addActionListener(l->{
+ systemTray.remove(getTrayIcon());
+ Platform.runLater(()->{
+ //getStage().setIconified(false);
+ getStage().show();
+ });
+ });
+
+ MenuItem exitItem = new MenuItem("Exit");
+ exitItem.addActionListener(l->{
+ systemTray.remove(getTrayIcon());
+ onQuitApp();
+ Platform.exit();
+ });
+
+ popup.add(showItem);
+ popup.addSeparator();
+ popup.add(exitItem);
+
+ TrayIcon trayIcon = new TrayIcon(
+ Toolkit.getDefaultToolkit().getImage(Main.class.getResource("app_icon.png")),
+ "Stream-Pi Server",
+ popup
+ );
+
+ trayIcon.setImageAutoSize(true);
+
+ this.trayIcon = trayIcon;
+ }
+
+ private TrayIcon trayIcon = null;
+
+ public TrayIcon getTrayIcon()
+ {
+ return trayIcon;
+ }
+
+ @Override
+ public void handleMinorException(MinorException e) {
+ getLogger().log(Level.SEVERE, e.getMessage());
+ e.printStackTrace();
+
+ Platform.runLater(()-> new StreamPiAlert(e.getTitle(), e.getShortMessage(), StreamPiAlertType.WARNING).show());
+ }
+
+ @Override
+ public void handleSevereException(SevereException e) {
+ getLogger().log(Level.SEVERE, e.getMessage());
+ e.printStackTrace();
+
+ Platform.runLater(()->{
+ StreamPiAlert alert = new StreamPiAlert(e.getTitle(), e.getShortMessage(), StreamPiAlertType.ERROR);
+
+ alert.setOnClicked(new StreamPiAlertListener()
+ {
+ @Override
+ public void onClick(String txt)
+ {
+ onQuitApp();
+ Platform.exit();
+ }
+ });
+
+ alert.show();
+ });
+ }
+
+ @Override
+ public synchronized boolean onNormalActionClicked(NormalAction action) {
+ try{
+ getLogger().info("action "+action.getID()+" clicked!");
+
+ action.onActionClicked();
+ return true;
+ }
+ catch (Exception e)
+ {
+ handleMinorException(new MinorException(
+ "action Execution Failed!",
+ "Error running action at ["+action.getLocation().getRow()+","+action.getLocation().getCol()+"] ("+action.getDisplayText()+")\n"+
+ "Check stacktrace/log to know what exactly happened\n\nMessage : \n"+e.getMessage() )
+ );
+ return false;
+ }
+ }
+
+ @Override
+ public void clearTemp() {
+ Platform.runLater(() -> {
+ getDashboardPane().getClientDetailsPane().refresh();
+ getDashboardPane().getActionGridPane().clear();
+ getDashboardPane().getActionDetailsPane().clear();
+ getSettingsPane().getClientsSettings().loadData();
+ });
+ }
+
+ @Override
+ public void saveServerProperties() {
+ try {
+ NormalActionPlugins.getInstance().saveServerSettings();
+ getSettingsPane().getPluginsSettings().loadPlugins();
+ } catch (MinorException e) {
+ e.printStackTrace();
+ handleMinorException(e);
+ }
+ }
+
+ @Override
+ public com.stream_pi.util.platform.Platform getPlatform() {
+ return ServerInfo.getInstance().getPlatformType();
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/info/License.java
@@ -0,0 +1,43 @@
+/*
+Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macropad
+Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Written by : Debayan Sutradhar (rnayabed)
+*/
+
+package com.stream_pi.server.info;
+
+public class License {
+ /**
+ * @return Formatted String containing the Stream-Pi License an also licenses of other opensource libraries used.
+ */
+ public static String getLicense()
+ {
+ return "Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macro Pad\n" +
+ "Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)\n" +
+ "\n" +
+ "This program is free software: you can redistribute it and/or modify\n" +
+ "it under the terms of the GNU General Public License as published by\n" +
+ "the Free Software Foundation, either version 3 of the License, or\n" +
+ "(at your option) any later version.\n" +
+ "\n" +
+ "This program is distributed in the hope that it will be useful,\n" +
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +
+ "GNU General Public License for more details.\n" +
+ "\n\n"+
+ "Opensource Libraries used :\n"+
+ "1. JavaFX - GNU General Public License with Classpath Exception\nhttp://openjdk.java.net/legal/gplv2+ce.html\n\n"+
+ "2. JSON - The JSON License\nhttps://www.json.org/license.html\n\n"+
+ "3. Ikonli - Apache License\nhttps://github.com/kordamp/ikonli/blob/master/LICENSE\n\n";
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/info/ServerInfo.java
@@ -0,0 +1,117 @@
+/*
+ServerInfo.java
+
+Stores basic information about the server - name, platform type
+
+Contributors: Debayan Sutradhar (@dubbadhar)
+ */
+
+package com.stream_pi.server.info;
+
+import com.stream_pi.util.platform.Platform;
+import com.stream_pi.util.platform.ReleaseStatus;
+import com.stream_pi.util.version.Version;
+
+public class ServerInfo {
+ private Version version;
+ private final ReleaseStatus releaseStatus;
+ private final Platform platformType;
+
+ private String prePath;
+
+ private Version minThemeSupportVersion;
+ private Version minPluginSupportVersion;
+ private Version commStandardVersion;
+
+ private static ServerInfo instance = null;
+
+ private String runnerFileName = null;
+ private boolean startMinimised = false;
+
+ private ServerInfo(){
+ version = new Version(1,0,0);
+ minThemeSupportVersion = new Version(1,0,0);
+ minPluginSupportVersion = new Version(1,0,0);
+ commStandardVersion = new Version(1,0,0);
+
+ releaseStatus = ReleaseStatus.EA;
+ prePath = "data/";
+
+ String osName = System.getProperty("os.name").toLowerCase();
+
+ if(osName.contains("windows"))
+ platformType = Platform.WINDOWS;
+ else if (osName.contains("linux"))
+ platformType = Platform.LINUX;
+ else if (osName.contains("mac"))
+ platformType = Platform.MAC;
+ else
+ platformType = Platform.UNKNOWN;
+
+
+ }
+
+
+ public String getPrePath() {
+ return prePath;
+ }
+
+ public void setStartMinimised(boolean startMinimised)
+ {
+ this.startMinimised = startMinimised;
+ }
+
+ public boolean isStartMinimised()
+ {
+ return startMinimised;
+ }
+
+ public void setRunnerFileName(String runnerFileName)
+ {
+ this.runnerFileName = runnerFileName;
+ }
+
+ public String getRunnerFileName()
+ {
+ return runnerFileName;
+ }
+
+ public static synchronized ServerInfo getInstance(){
+ if(instance == null)
+ {
+ instance = new ServerInfo();
+ }
+
+ return instance;
+ }
+
+
+ public Platform getPlatformType()
+ {
+ return platformType;
+ }
+
+ public Version getVersion() {
+ return version;
+ }
+
+ public ReleaseStatus getReleaseStatus()
+ {
+ return releaseStatus;
+ }
+
+ public Version getMinThemeSupportVersion()
+ {
+ return minThemeSupportVersion;
+ }
+
+ public Version getMinPluginSupportVersion()
+ {
+ return minPluginSupportVersion;
+ }
+
+ public Version getCommStandardVersion()
+ {
+ return commStandardVersion;
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/io/Config.java
@@ -0,0 +1,324 @@
+/*
+Config.java
+
+Contributor(s) : Debayan Sutradhar (@rnayabed)
+
+handler for config.xml
+ */
+
+package com.stream_pi.server.io;
+
+import java.io.File;
+import java.util.logging.Logger;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import com.stream_pi.server.info.ServerInfo;
+import com.stream_pi.util.exception.SevereException;
+import com.stream_pi.util.xmlconfighelper.XMLConfigHelper;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class Config {
+
+ private static Config instance = null;
+
+ private final File configFile;
+
+ private Document document;
+
+ private Config() throws SevereException {
+ try {
+ configFile = new File(ServerInfo.getInstance().getPrePath()+"config.xml");
+ DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+ document = docBuilder.parse(configFile);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new SevereException("Config", "unable to read config.xml");
+ }
+ }
+
+ public static synchronized Config getInstance() throws SevereException
+ {
+ if(instance == null)
+ instance = new Config();
+
+ return instance;
+ }
+
+ Logger logger = Logger.getLogger(Config.class.getName());
+
+ public void save() throws SevereException {
+ try {
+ logger.info("Saving config ...");
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ Result output = new StreamResult(configFile);
+ Source input = new DOMSource(document);
+
+ transformer.transform(input, output);
+ logger.info("... Done!");
+ } catch (Exception e) {
+ throw new SevereException("Config", "unable to save config.xml");
+ }
+ }
+
+
+ //Getters
+
+ //comms
+ private Element getCommsElement()
+ {
+ return (Element) document.getElementsByTagName("comms").item(0);
+ }
+
+ public String getServerName()
+ {
+ return XMLConfigHelper.getStringProperty(getCommsElement(), "name",
+ getDefaultServerName(), false, true, document, configFile);
+ }
+
+ public int getPort()
+ {
+ return XMLConfigHelper.getIntProperty(getCommsElement(), "port",
+ getDefaultPort(), false, true, document, configFile);
+ }
+
+ //default getters
+ public String getDefaultServerName()
+ {
+ return "StreamPi Server";
+ }
+
+ public int getDefaultPort()
+ {
+ return 2004;
+ }
+
+ private Element getServerElement()
+ {
+ return (Element) document.getElementsByTagName("server").item(0);
+ }
+
+
+ //server
+
+ private Element getActionGridElement()
+ {
+ return (Element) getServerElement().getElementsByTagName("action-grid").item(0);
+ }
+ public int getActionGridActionGap()
+ {
+ return XMLConfigHelper.getIntProperty(getActionGridElement(), "gap",
+ getDefaultActionGridActionGap(), false, true, document, configFile);
+ }
+
+ public int getActionGridActionSize()
+ {
+ return XMLConfigHelper.getIntProperty(getActionGridElement(), "size",
+ getDefaultActionGridSize(), false, true, document, configFile);
+ }
+
+
+ public String getCurrentThemeFullName()
+ {
+ return XMLConfigHelper.getStringProperty(getServerElement(), "current-theme-full-name",
+ getDefaultCurrentThemeFullName(), false, true, document, configFile);
+ }
+
+ public String getThemesPath()
+ {
+ return XMLConfigHelper.getStringProperty(getServerElement(), "themes-path",
+ getDefaultThemesPath(), false, true, document, configFile);
+ }
+
+
+ public String getPluginsPath()
+ {
+ return XMLConfigHelper.getStringProperty(getServerElement(), "plugins-path",
+ getDefaultPluginsPath(), false, true, document, configFile);
+ }
+
+ //default getters
+ public String getDefaultCurrentThemeFullName()
+ {
+ return "com.StreamPi.DefaultLight";
+ }
+
+ public String getDefaultThemesPath()
+ {
+ return "Themes/";
+ }
+
+ public String getDefaultPluginsPath()
+ {
+ return "Plugins/";
+ }
+
+
+ //server > startup-window-size
+
+ private Element getStartupWindowSizeElement()
+ {
+ return (Element) getServerElement().getElementsByTagName("startup-window-size").item(0);
+ }
+
+ public double getStartupWindowWidth()
+ {
+ return XMLConfigHelper.getDoubleProperty(getStartupWindowSizeElement(), "width",
+ getDefaultStartupWindowWidth(), false, true, document, configFile);
+ }
+
+ public double getStartupWindowHeight()
+ {
+ return XMLConfigHelper.getDoubleProperty(getStartupWindowSizeElement(), "height",
+ getDefaultStartupWindowHeight(), false, true, document, configFile);
+ }
+
+ //default getters
+ public int getDefaultStartupWindowWidth()
+ {
+ return 1024;
+ }
+
+ public int getDefaultStartupWindowHeight()
+ {
+ return 768;
+ }
+
+
+ //others
+ private Element getOthersElement()
+ {
+ return (Element) document.getElementsByTagName("others").item(0);
+ }
+
+ public boolean getStartOnBoot()
+ {
+ return XMLConfigHelper.getBooleanProperty(getOthersElement(), "start-on-boot",
+ getDefaultStartOnBoot(), false, true, document, configFile);
+ }
+
+ public boolean getCloseOnX()
+ {
+ return XMLConfigHelper.getBooleanProperty(getOthersElement(), "close-on-x",
+ getDefaultCloseOnX(), false, true, document, configFile);
+ }
+
+ public boolean isFirstTimeUse()
+ {
+ return XMLConfigHelper.getBooleanProperty(getOthersElement(), "first-time-use", true, false, true, document, configFile);
+ }
+
+ public boolean isAllowDonatePopup()
+ {
+ return XMLConfigHelper.getBooleanProperty(getOthersElement(), "allow-donate-popup", true, false, true, document, configFile);
+ }
+
+ //default getters
+ public boolean getDefaultStartOnBoot()
+ {
+ return false;
+ }
+
+ public boolean getDefaultCloseOnX()
+ {
+ return false;
+ }
+
+
+ //Setters
+
+ //comms
+ public void setServerName(String name)
+ {
+ getCommsElement().getElementsByTagName("name").item(0).setTextContent(name);
+ }
+
+ public void setServerPort(int port)
+ {
+ getCommsElement().getElementsByTagName("port").item(0).setTextContent(port+"");
+ }
+
+ //server
+
+ public int getDefaultActionGridActionGap()
+ {
+ return 5;
+ }
+
+ public int getDefaultActionGridSize()
+ {
+ return 100;
+ }
+
+ public void setActionGridSize(int size)
+ {
+ getActionGridElement().getElementsByTagName("size").item(0).setTextContent(size+"");
+ }
+
+ public void setActionGridGap(int size)
+ {
+ getActionGridElement().getElementsByTagName("gap").item(0).setTextContent(size+"");
+ }
+
+ public void setPluginsPath(String path)
+ {
+ getServerElement().getElementsByTagName("plugins-path").item(0).setTextContent(path);
+ }
+
+ public void setThemesPath(String path)
+ {
+ getServerElement().getElementsByTagName("themes-path").item(0).setTextContent(path);
+ }
+
+ public void setCurrentThemeFullName(String themeName)
+ {
+ getServerElement().getElementsByTagName("current-theme-full-name").item(0).setTextContent(themeName);
+ }
+
+ //server > startup-window-size
+ public void setStartupWindowSize(double width, double height)
+ {
+ setStartupWindowWidth(width);
+ setStartupWindowHeight(height);
+ }
+
+ public void setStartupWindowWidth(double width)
+ {
+ getStartupWindowSizeElement().getElementsByTagName("width").item(0).setTextContent(width+"");
+ }
+
+ public void setStartupWindowHeight(double height)
+ {
+ getStartupWindowSizeElement().getElementsByTagName("height").item(0).setTextContent(height+"");
+ }
+
+ //others
+ public void setStartupOnBoot(boolean value)
+ {
+ getOthersElement().getElementsByTagName("start-on-boot").item(0).setTextContent(value+"");
+ }
+
+ public void setCloseOnX(boolean value)
+ {
+ getOthersElement().getElementsByTagName("close-on-x").item(0).setTextContent(value+"");
+ }
+
+ public void setFirstTimeUse(boolean value)
+ {
+ getOthersElement().getElementsByTagName("first-time-use").item(0).setTextContent(value+"");
+ }
+
+ public void setAllowDonatePopup(boolean value)
+ {
+ getOthersElement().getElementsByTagName("allow-donate-popup").item(0).setTextContent(value+"");
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/uipropertybox/UIPropertyBox.java
@@ -0,0 +1,81 @@
+package com.stream_pi.server.uipropertybox;
+
+import com.stream_pi.actionapi.actionproperty.property.ControlType;
+import com.stream_pi.actionapi.actionproperty.property.Type;
+import javafx.scene.Node;
+import javafx.scene.control.ComboBox;
+import javafx.scene.control.Slider;
+import javafx.scene.control.TextField;
+import javafx.scene.control.ToggleButton;
+
+public class UIPropertyBox
+{
+ private Node controlNode;
+ private boolean canBeBlank;
+ private String displayName;
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public boolean isCanBeBlank() {
+ return canBeBlank;
+ }
+
+ private int index;
+
+ private ControlType controlType;
+ private Type type;
+
+ public UIPropertyBox(int index, String displayName, Node controlNode, ControlType controlType, Type type, boolean canBeBlank)
+ {
+ this.index = index;
+ this.displayName = displayName;
+ this.controlNode = controlNode;
+ this.controlType = controlType;
+ this.type = type;
+ this.canBeBlank = canBeBlank;
+ }
+
+ public ControlType getControlType()
+ {
+ return controlType;
+ }
+
+ public Node getControlNode()
+ {
+ return controlNode;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public Type getType()
+ {
+ return type;
+ }
+
+ public String getRawValue()
+ {
+ String rawValue = null;
+
+ if (controlType == ControlType.TEXT_FIELD)
+ rawValue = ((TextField) controlNode).getText();
+ else if (controlType == ControlType.COMBO_BOX)
+ rawValue = ((ComboBox<String>) controlNode).getSelectionModel().getSelectedIndex() + "";
+ else if (controlType == ControlType.SLIDER_DOUBLE)
+ rawValue = ((Slider) controlNode).getValue() + "";
+ else if (controlType == ControlType.SLIDER_INTEGER)
+ rawValue = Math.round(((Slider) controlNode).getValue()) + "";
+ else if (controlType == ControlType.TOGGLE) {
+ ToggleButton toggleButton = ((ToggleButton) controlNode);
+ if (toggleButton.isSelected())
+ rawValue = "true";
+ else
+ rawValue = "false";
+ }
+
+ return rawValue;
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/Base.java
@@ -0,0 +1,270 @@
+package com.stream_pi.server.window;
+
+import com.stream_pi.server.connection.ServerListener;
+import com.stream_pi.server.io.Config;
+import com.stream_pi.server.info.ServerInfo;
+import com.stream_pi.server.Main;
+import com.stream_pi.server.window.dashboard.DashboardBase;
+import com.stream_pi.server.window.settings.SettingsBase;
+import com.stream_pi.themeapi.Theme;
+import com.stream_pi.themeapi.Themes;
+import com.stream_pi.util.alert.StreamPiAlert;
+import com.stream_pi.util.exception.MinorException;
+import com.stream_pi.util.exception.SevereException;
+import com.stream_pi.util.loggerhelper.StreamPiLogFileHandler;
+
+import javafx.application.HostServices;
+import javafx.scene.image.Image;
+import javafx.scene.layout.StackPane;
+import javafx.scene.text.Font;
+import javafx.stage.Stage;
+
+import java.util.logging.Logger;
+
+public abstract class Base extends StackPane implements ExceptionAndAlertHandler, ServerListener {
+
+ private Config config;
+
+ private ServerInfo serverInfo;
+
+ private Stage stage;
+
+ private HostServices hostServices;
+
+ public Logger getLogger(){
+ return logger;
+ }
+
+ private SettingsBase settingsBase;
+ private DashboardBase dashboardBase;
+
+ private StackPane alertStackPane;
+
+ public void setHostServices(HostServices hostServices)
+ {
+ this.hostServices = hostServices;
+ }
+
+ public HostServices getHostServices()
+ {
+ return hostServices;
+ }
+
+ private Logger logger = null;
+ private StreamPiLogFileHandler logFileHandler = null;
+
+ public void initLogger() throws SevereException
+ {
+ try
+ {
+ if(logger != null)
+ return;
+
+ logger = Logger.getLogger("");
+ logFileHandler = new StreamPiLogFileHandler(ServerInfo.getInstance().getPrePath()+"../streampi.log");
+ logger.addHandler(logFileHandler);
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ throw new SevereException("Cant get logger started!");
+ }
+ }
+
+ public void closeLogger()
+ {
+ if(logFileHandler != null)
+ logFileHandler.close();
+ }
+
+ public void initBase() throws SevereException {
+ initLogger();
+
+ getChildren().clear();
+
+ stage = (Stage) getScene().getWindow();
+
+ getStage().getIcons().add(new Image(Main.class.getResourceAsStream("app_icon.png")));
+
+ getStage().setMinWidth(500);
+ getStage().setMinHeight(500);
+
+ config = Config.getInstance();
+
+ stage.setWidth(config.getStartupWindowWidth());
+ stage.setHeight(config.getStartupWindowHeight());
+ stage.centerOnScreen();
+
+
+ serverInfo = ServerInfo.getInstance();
+
+
+ initThemes();
+
+ settingsBase = new SettingsBase(getHostServices(), this, this);
+ settingsBase.prefWidthProperty().bind(widthProperty());
+ settingsBase.prefHeightProperty().bind(heightProperty());
+
+ dashboardBase = new DashboardBase(this, getHostServices());
+ dashboardBase.prefWidthProperty().bind(widthProperty());
+ dashboardBase.prefHeightProperty().bind(heightProperty());
+
+ alertStackPane = new StackPane();
+ alertStackPane.setVisible(false);
+
+ StreamPiAlert.setParent(alertStackPane);
+
+ getChildren().addAll(settingsBase, dashboardBase, alertStackPane);
+
+ dashboardBase.toFront();
+
+
+ }
+
+ public void initThemes() throws SevereException {
+ clearStylesheets();
+
+ registerThemes();
+ applyDefaultStylesheet();
+ applyDefaultTheme();
+ }
+
+ public Stage getStage()
+ {
+ return stage;
+ }
+
+ public void applyDefaultStylesheet()
+ {
+ logger.info("Applying default stylesheet ...");
+
+ Font.loadFont(Main.class.getResourceAsStream("Roboto.ttf"), 13);
+ getStylesheets().add(Main.class.getResource("style.css").toExternalForm());
+
+ logger.info("... Done!");
+ }
+
+ public DashboardBase getDashboardPane()
+ {
+ return dashboardBase;
+ }
+
+ public SettingsBase getSettingsPane()
+ {
+ return settingsBase;
+ }
+
+
+ public Config getConfig()
+ {
+ return config;
+ }
+
+ public ServerInfo getServerInfo()
+ {
+ return serverInfo;
+ }
+
+ private Theme currentTheme;
+ public Theme getCurrentTheme()
+ {
+ return currentTheme;
+ }
+
+ public void applyTheme(Theme t)
+ {
+ logger.info("Applying theme '"+t.getFullName()+"' ...");
+
+ if(t.getFonts() != null)
+ {
+ for(String fontFile : t.getFonts())
+ {
+ Font.loadFont(fontFile.replace("%20",""), 13);
+ }
+ }
+
+ currentTheme = t;
+ getStylesheets().addAll(t.getStylesheets());
+
+ logger.info("... Done!");
+ }
+
+ public void clearStylesheets()
+ {
+ getStylesheets().clear();
+ }
+
+ Themes themes;
+ public void registerThemes() throws SevereException
+ {
+ logger.info("Loading themes ...");
+ themes = new Themes(getConfig().getThemesPath(), getConfig().getCurrentThemeFullName(), serverInfo.getMinThemeSupportVersion());
+
+ if(themes.getErrors().size()>0)
+ {
+ StringBuilder themeErrors = new StringBuilder();
+
+ for(MinorException eachException : themes.getErrors())
+ {
+ themeErrors.append("\n * ").append(eachException.getShortMessage());
+ }
+
+ if(themes.getIsBadThemeTheCurrentOne())
+ {
+ themeErrors.append("\n\nReverted to default theme! (").append(getConfig().getDefaultCurrentThemeFullName()).append(")");
+
+ getConfig().setCurrentThemeFullName(getConfig().getDefaultCurrentThemeFullName());
+ getConfig().save();
+ }
+
+ handleMinorException(new MinorException("Theme Loading issues", themeErrors.toString()));
+ }
+
+
+ logger.info("... Done!");
+ }
+
+ public Themes getThemes()
+ {
+ return themes;
+ }
+
+ public void applyDefaultTheme()
+ {
+ logger.info("Applying default theme ...");
+
+
+
+ boolean foundTheme = false;
+ for(Theme t: themes.getThemeList())
+ {
+ if(t.getFullName().equals(config.getCurrentThemeFullName()))
+ {
+ foundTheme = true;
+ applyTheme(t);
+ break;
+ }
+ }
+
+ if(foundTheme)
+ logger.info("... Done!");
+ else
+ {
+ logger.info("Theme not found. reverting to light theme ...");
+ try {
+ Config.getInstance().setCurrentThemeFullName("com.streampi.DefaultLight");
+ Config.getInstance().save();
+
+ applyDefaultTheme();
+ }
+ catch (SevereException e)
+ {
+ handleSevereException(e);
+ }
+ }
+
+
+ }
+
+
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/ExceptionAndAlertHandler.java
@@ -0,0 +1,9 @@
+package com.stream_pi.server.window;
+
+import com.stream_pi.util.exception.MinorException;
+import com.stream_pi.util.exception.SevereException;
+
+public interface ExceptionAndAlertHandler {
+ void handleMinorException(MinorException e);
+ void handleSevereException(SevereException e);
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/dashboard/ClientDetailsPane.java
@@ -0,0 +1,163 @@
+package com.stream_pi.server.window.dashboard;
+
+import com.stream_pi.server.client.Client;
+import com.stream_pi.server.client.ClientProfile;
+import com.stream_pi.server.connection.ClientConnection;
+import com.stream_pi.server.connection.ClientConnections;
+import javafx.collections.FXCollections;
+import javafx.geometry.Insets;
+import javafx.scene.CacheHint;
+import javafx.scene.control.*;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.VBox;
+import javafx.util.Callback;
+
+public class ClientDetailsPane extends HBox {
+
+ private DashboardInterface dashboard;
+
+ public ClientDetailsPane(DashboardInterface dashboard)
+ {
+ this.dashboard = dashboard;
+
+ VBox.setVgrow(this, Priority.NEVER);
+ getStyleClass().add("client_details_pane");
+ setPadding(new Insets(10));
+ setMinHeight(90);
+
+ initUI();
+ loadData();
+
+ setCache(true);
+ setCacheHint(CacheHint.SPEED);
+ }
+
+ private ComboBox<ClientConnection> clientsComboBox;
+ private Label noClientsConnectedLabel;
+ private ComboBox<ClientProfile> clientProfilesComboBox;
+
+
+ public void initUI()
+ {
+ noClientsConnectedLabel = new Label("No Clients Connected");
+ noClientsConnectedLabel.managedProperty().bind(noClientsConnectedLabel.visibleProperty());
+
+ clientsComboBox = new ComboBox<>();
+ clientsComboBox.setPromptText("Choose client");
+
+ clientsComboBox.valueProperty().addListener((observableValue, oldVal, newVal) -> {
+ if(oldVal!=newVal && newVal!=null)
+ {
+ dashboard.newSelectedClientConnection(newVal);
+ clientProfilesComboBox.setItems(FXCollections.observableArrayList(newVal.getClient().getAllClientProfiles()));
+ clientProfilesComboBox.setVisible(true);
+ }
+ });
+
+ clientsComboBox.managedProperty().bind(clientsComboBox.visibleProperty());
+
+
+ Callback<ListView<ClientConnection>, ListCell<ClientConnection>> clientsComboBoxFactory = new Callback<>() {
+ @Override
+ public ListCell<ClientConnection> call(ListView<ClientConnection> clientConnectionListView) {
+
+ return new ListCell<>() {
+ @Override
+ protected void updateItem(ClientConnection clientConnection, boolean b) {
+ super.updateItem(clientConnection, b);
+
+ if(clientConnection == null)
+ {
+ setText("Choose client");
+ }
+ else
+ {
+ Client client = clientConnection.getClient();
+ setText(client.getNickName());
+ }
+ }
+ };
+ }
+ };
+ clientsComboBox.setCellFactory(clientsComboBoxFactory);
+ clientsComboBox.setButtonCell(clientsComboBoxFactory.call(null));
+
+
+
+ clientProfilesComboBox = new ComboBox<>();
+ clientProfilesComboBox.setPromptText("Choose Profile");
+ clientProfilesComboBox.valueProperty().addListener((observableValue, oldVal, newVal) -> {
+ if(oldVal!=newVal && newVal!=null)
+ {
+ dashboard.newSelectedClientProfile(newVal);
+ }
+ });
+
+
+ clientProfilesComboBox.managedProperty().bind(clientProfilesComboBox.visibleProperty());
+ Callback<ListView<ClientProfile>, ListCell<ClientProfile>> clientProfilesComboBoxFactory = new Callback<ListView<ClientProfile>, ListCell<ClientProfile>>() {
+ @Override
+ public ListCell<ClientProfile> call(ListView<ClientProfile> clientProfileListView) {
+ return new ListCell<>()
+ {
+ @Override
+ protected void updateItem(ClientProfile profile, boolean b) {
+ super.updateItem(profile, b);
+
+ if(profile == null)
+ {
+ setText("Choose Profile");
+ }
+ else
+ {
+ setText(profile.getName());
+ }
+ }
+ };
+ }
+ };
+ clientProfilesComboBox.setCellFactory(clientProfilesComboBoxFactory);
+ clientProfilesComboBox.setButtonCell(clientProfilesComboBoxFactory.call(null));
+
+ VBox stack = new VBox(noClientsConnectedLabel, clientsComboBox, clientProfilesComboBox);
+ stack.setSpacing(10);
+
+ getChildren().addAll(stack);
+
+ }
+
+
+ private void loadData()
+ {
+ clientsComboBox.getSelectionModel().clearSelection();
+ clientProfilesComboBox.getSelectionModel().clearSelection();
+
+ if(ClientConnections.getInstance().getConnections().size() == 0)
+ {
+ noClientsConnectedLabel.setVisible(true);
+
+ clientsComboBox.setVisible(false);
+
+ clientProfilesComboBox.setVisible(false);
+
+
+ dashboard.newSelectedClientConnection(null);
+
+ }
+ else
+ {
+ noClientsConnectedLabel.setVisible(false);
+
+ clientsComboBox.setVisible(true);
+ clientProfilesComboBox.setVisible(false);
+
+ clientsComboBox.setItems(FXCollections.observableArrayList(ClientConnections.getInstance().getConnections()));
+ }
+ }
+
+ public void refresh()
+ {
+ loadData();
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/dashboard/DashboardBase.java
@@ -0,0 +1,132 @@
+package com.stream_pi.server.window.dashboard;
+
+import java.util.logging.Logger;
+
+import com.stream_pi.server.client.ClientProfile;
+import com.stream_pi.server.connection.ClientConnection;
+import com.stream_pi.server.window.dashboard.actiongridpane.ActionGridPane;
+import com.stream_pi.server.window.dashboard.actiondetailpane.ActionDetailsPane;
+import com.stream_pi.server.window.ExceptionAndAlertHandler;
+import com.stream_pi.util.exception.SevereException;
+import javafx.application.HostServices;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.VBox;
+
+public class DashboardBase extends HBox implements DashboardInterface {
+
+ private final VBox leftPane;
+
+ private Logger logger;
+
+ public ClientProfile currentClientProfile;
+
+ private ExceptionAndAlertHandler exceptionAndAlertHandler;
+
+
+ public DashboardBase(ExceptionAndAlertHandler exceptionAndAlertHandler, HostServices hostServices)
+ {
+ this.exceptionAndAlertHandler = exceptionAndAlertHandler;
+ logger = Logger.getLogger(DashboardBase.class.getName());
+ leftPane = new VBox();
+
+ HBox.setHgrow(leftPane, Priority.ALWAYS);
+ getChildren().add(leftPane);
+
+ setPluginsPane(new PluginsPane(hostServices));
+
+ setClientDetailsPane(new ClientDetailsPane(this));
+
+ setActionGridPane(new ActionGridPane(exceptionAndAlertHandler));
+
+ setActionDetailsPane(new ActionDetailsPane(exceptionAndAlertHandler, hostServices));
+
+ getActionGridPane().setActionDetailsPaneListener(getActionDetailsPane());
+ }
+
+
+
+ private PluginsPane pluginsPane;
+ private void setPluginsPane(PluginsPane pluginsPane)
+ {
+ this.pluginsPane = pluginsPane;
+ getChildren().add(this.pluginsPane);
+ }
+ public PluginsPane getPluginsPane()
+ {
+ return pluginsPane;
+ }
+
+ private ClientDetailsPane clientDetailsPane;
+ private void setClientDetailsPane(ClientDetailsPane clientDetailsPane)
+ {
+ this.clientDetailsPane = clientDetailsPane;
+ leftPane.getChildren().add(this.clientDetailsPane);
+ }
+ public ClientDetailsPane getClientDetailsPane()
+ {
+ return clientDetailsPane;
+ }
+
+ private ActionGridPane actionGridPane;
+ private void setActionGridPane(ActionGridPane actionGridPane)
+ {
+ this.actionGridPane = actionGridPane;
+ leftPane.getChildren().add(this.actionGridPane);
+ }
+ public ActionGridPane getActionGridPane()
+ {
+ return actionGridPane;
+ }
+
+ private ActionDetailsPane actionDetailsPane;
+ private void setActionDetailsPane(ActionDetailsPane actionDetailsPane)
+ {
+ this.actionDetailsPane = actionDetailsPane;
+ leftPane.getChildren().add(this.actionDetailsPane);
+ }
+ public ActionDetailsPane getActionDetailsPane()
+ {
+ return actionDetailsPane;
+ }
+
+ public void newSelectedClientConnection(ClientConnection clientConnection)
+ {
+ if(clientConnection == null)
+ {
+ logger.info("Remove action grid");
+ }
+ else
+ {
+ getActionDetailsPane().setClient(clientConnection.getClient());
+ getActionGridPane().setClient(clientConnection.getClient());
+ }
+ }
+
+ public void newSelectedClientProfile(ClientProfile clientProfile)
+ {
+ this.currentClientProfile = clientProfile;
+
+ getActionDetailsPane().setClientProfile(clientProfile);
+
+ drawProfile(this.currentClientProfile);
+ }
+
+ public void drawProfile(ClientProfile clientProfile)
+ {
+ logger.info("Drawing ...");
+
+ getActionGridPane().setClientProfile(clientProfile);
+
+ try {
+ getActionGridPane().renderGrid();
+ getActionGridPane().renderActions();
+ }
+ catch (SevereException e)
+ {
+ exceptionAndAlertHandler.handleSevereException(e);
+ }
+
+
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/dashboard/DashboardInterface.java
@@ -0,0 +1,10 @@
+package com.stream_pi.server.window.dashboard;
+
+import com.stream_pi.server.client.ClientProfile;
+import com.stream_pi.server.connection.ClientConnection;
+
+public interface DashboardInterface {
+ void newSelectedClientConnection(ClientConnection clientConnection);
+ void newSelectedClientProfile(ClientProfile clientProfile);
+
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/dashboard/DonatePopupContent.java
@@ -0,0 +1,64 @@
+package com.stream_pi.server.window.dashboard;
+
+import com.stream_pi.server.io.Config;
+import com.stream_pi.server.window.ExceptionAndAlertHandler;
+import com.stream_pi.util.alert.StreamPiAlert;
+import com.stream_pi.util.alert.StreamPiAlertListener;
+import com.stream_pi.util.alert.StreamPiAlertType;
+import com.stream_pi.util.exception.MinorException;
+import com.stream_pi.util.exception.SevereException;
+
+import javafx.application.HostServices;
+import javafx.scene.control.Hyperlink;
+import javafx.scene.control.Label;
+import javafx.scene.layout.VBox;
+
+public class DonatePopupContent{
+ public DonatePopupContent(HostServices hostServices, ExceptionAndAlertHandler exceptionAndAlertHandler)
+ {
+ Label label = new Label("We are a very small team working very hard on this project for best user experience.\n\n" +
+ "Something like StreamPi takes time, effort and resources. But we will always keep this 100% opensource and free.\n\n" +
+ "If you find this project helpful, and would want to help us, please consider donating :)\n\n"+
+ "If you are unable to do so even a small shoutout and share across social media would be very helpful.");
+
+ label.setWrapText(true);
+ label.getStyleClass().add("donate_request_popup_label");
+
+ Hyperlink patreonLink = new Hyperlink("Our Patreon");
+ patreonLink.setOnAction(event ->{
+ hostServices.showDocument("https://patreon.com/streampi");
+ });
+ patreonLink.getStyleClass().add("donate_request_popup_patreon_link");
+
+ VBox pane = new VBox(label, patreonLink);
+ pane.setSpacing(5.0);
+
+ streamPiAlert = new StreamPiAlert("Hey!", StreamPiAlertType.INFORMATION, pane);
+
+ streamPiAlert.setOnClicked(new StreamPiAlertListener()
+ {
+ @Override
+ public void onClick(String buttonClicked)
+ {
+ try
+ {
+ Config.getInstance().setAllowDonatePopup(false);
+ Config.getInstance().save();
+ }
+ catch(SevereException e)
+ {
+ exceptionAndAlertHandler.handleSevereException(e);
+ }
+ }
+
+ });
+ }
+
+ private StreamPiAlert streamPiAlert;
+
+ public void show()
+ {
+ streamPiAlert.show();
+ }
+
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/dashboard/PluginsPane.java
@@ -0,0 +1,261 @@
+package com.stream_pi.server.window.dashboard;
+import com.stream_pi.actionapi.action.Action;
+import com.stream_pi.actionapi.action.ActionType;
+import com.stream_pi.actionapi.action.DisplayTextAlignment;
+import com.stream_pi.actionapi.actionproperty.property.Property;
+import com.stream_pi.actionapi.actionproperty.property.Type;
+import com.stream_pi.actionapi.normalaction.NormalAction;
+import com.stream_pi.actionapi.otheractions.CombineAction;
+import com.stream_pi.actionapi.otheractions.FolderAction;
+import com.stream_pi.server.action.NormalActionPlugins;
+
+import javafx.application.HostServices;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.CacheHint;
+import javafx.scene.Node;
+import javafx.scene.control.*;
+import javafx.scene.image.ImageView;
+import javafx.scene.input.ClipboardContent;
+import javafx.scene.input.Dragboard;
+import javafx.scene.input.TransferMode;
+import javafx.scene.layout.*;
+import org.kordamp.ikonli.javafx.FontIcon;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class PluginsPane extends VBox {
+
+ private Button settingsButton;
+
+ public PluginsPane(HostServices hostServices)
+ {
+ setMinWidth(250);
+ getStyleClass().add("plugins_pane");
+ setPadding(new Insets(10));
+
+ setSpacing(10.0);
+
+ this.hostServices = hostServices;
+
+ initUI();
+ }
+
+ private Accordion pluginsAccordion;
+
+ public void initUI()
+ {
+ pluginsAccordion = new Accordion();
+ pluginsAccordion.setCache(true);
+
+ Region r = new Region();
+ VBox.setVgrow(r, Priority.ALWAYS);
+
+ settingsButton = new Button();
+
+ FontIcon cog = new FontIcon("fas-cog");
+
+ settingsButton.setGraphic(cog);
+
+ HBox settingsHBox = new HBox(settingsButton);
+ settingsHBox.setAlignment(Pos.CENTER_RIGHT);
+
+ getChildren().addAll(new Label("Plugins"), pluginsAccordion, r, settingsHBox);
+ }
+
+ public Button getSettingsButton()
+ {
+ return settingsButton;
+ }
+
+ public void clearData()
+ {
+ pluginsAccordion.getPanes().clear();
+ }
+
+ public void loadData()
+ {
+ HashMap<String, ArrayList<NormalAction>> sortedPlugins = NormalActionPlugins.getInstance().getSortedPlugins();
+
+ for(String eachCategory : sortedPlugins.keySet())
+ {
+ VBox vBox = new VBox();
+ vBox.setSpacing(5);
+
+
+ TitledPane pane = new TitledPane(eachCategory, vBox);
+ for(NormalAction eachAction : sortedPlugins.get(eachCategory))
+ {
+ if(!eachAction.isVisibleInPluginsPane())
+ continue;
+
+ Button eachNormalActionPluginButton = new Button();
+ HBox.setHgrow(eachNormalActionPluginButton, Priority.ALWAYS);
+ eachNormalActionPluginButton.setMaxWidth(Double.MAX_VALUE);
+ eachNormalActionPluginButton.setAlignment(Pos.CENTER_LEFT);
+
+ Node graphic = eachAction.getServerButtonGraphic();
+
+ if(graphic == null)
+ {
+ FontIcon cogs = new FontIcon("fas-cogs");
+ cogs.getStyleClass().add("dashboard_plugins_pane_action_icon");
+ eachNormalActionPluginButton.setGraphic(cogs);
+ }
+ else
+ {
+ if(graphic instanceof FontIcon)
+ {
+ FontIcon fi = (FontIcon) graphic;
+ eachNormalActionPluginButton.setGraphic(fi);
+ }
+ else if(graphic instanceof ImageView)
+ {
+ ImageView iv = (ImageView) graphic;
+ iv.getStyleClass().add("dashboard_plugins_pane_action_icon_imageview");
+ iv.setPreserveRatio(false);
+ eachNormalActionPluginButton.setGraphic(iv);
+ }
+ }
+ eachNormalActionPluginButton.setText(eachAction.getName());
+
+
+ eachNormalActionPluginButton.setOnDragDetected(mouseEvent -> {
+ Dragboard db = eachNormalActionPluginButton.startDragAndDrop(TransferMode.ANY);
+
+ ClipboardContent content = new ClipboardContent();
+
+ content.put(Action.getDataFormat(), createFakeAction(eachAction, "Untitled action"));
+
+ db.setContent(content);
+
+ mouseEvent.consume();
+ });
+
+
+
+ HBox hBox = new HBox(eachNormalActionPluginButton);
+ hBox.setSpacing(5.0);
+ hBox.setAlignment(Pos.TOP_LEFT);
+
+ HBox.setHgrow(eachNormalActionPluginButton, Priority.ALWAYS);
+
+ if(eachAction.getHelpLink() != null) {
+ Button helpButton = new Button();
+ FontIcon questionIcon = new FontIcon("fas-question");
+ questionIcon.getStyleClass().add("dashboard_plugins_pane_action_help_icon");
+ helpButton.setGraphic(questionIcon);
+ helpButton.setOnAction(event -> hostServices.showDocument(eachAction.getHelpLink()));
+
+ hBox.getChildren().add(helpButton);
+ }
+
+
+ vBox.getChildren().add(hBox);
+ }
+
+ if(vBox.getChildren().size() > 0)
+ pluginsAccordion.getPanes().add(pane);
+ }
+ }
+
+
+ private HostServices hostServices;
+
+ public Action createFakeAction(Action action, String displayText)
+ {
+ Action newAction = new Action(action.getActionType());
+
+ if(action.getActionType() == ActionType.NORMAL)
+ {
+ newAction.setModuleName(action.getModuleName());
+ newAction.setVersion(action.getVersion());
+ newAction.setName(action.getName());
+ }
+
+ newAction.setClientProperties(action.getClientProperties());
+
+ for(Property property : newAction.getClientProperties().get())
+ {
+ if(property.getType() == Type.STRING || property.getType() == Type.INTEGER || property.getType() == Type.DOUBLE)
+ property.setRawValue(property.getDefaultRawValue());
+ }
+
+ // newAction.setLocation(location);
+
+ newAction.setIDRandom();
+
+
+ newAction.setShowDisplayText(true);
+ newAction.setDisplayText(displayText);
+ newAction.setDisplayTextAlignment(DisplayTextAlignment.CENTER);
+ newAction.setShowIcon(false);
+ newAction.setHasIcon(false);
+
+ //action.setParent(root);
+
+ newAction.setBgColourHex("");
+ newAction.setDisplayTextFontColourHex("");
+
+ return newAction;
+ }
+
+ public void loadOtherActions()
+ {
+ VBox vBox = new VBox();
+
+ Button folderActionButton = new Button("Folder");
+ folderActionButton.setMaxWidth(Double.MAX_VALUE);
+ folderActionButton.setAlignment(Pos.CENTER_LEFT);
+ FontIcon folder = new FontIcon("fas-folder");
+ folderActionButton.setGraphic(folder);
+
+ folderActionButton.setOnDragDetected(mouseEvent -> {
+ Dragboard db = folderActionButton.startDragAndDrop(TransferMode.ANY);
+
+ ClipboardContent content = new ClipboardContent();
+
+ content.put(Action.getDataFormat(), createFakeAction(new FolderAction(), "Untitled Folder"));
+
+ db.setContent(content);
+
+ mouseEvent.consume();
+ });
+
+
+
+
+ Button combineActionButton = new Button("Combine");
+ combineActionButton.setMaxWidth(Double.MAX_VALUE);
+ combineActionButton.setAlignment(Pos.CENTER_LEFT);
+ FontIcon list = new FontIcon("fas-list");
+ combineActionButton.setGraphic(list);
+
+ combineActionButton.setOnDragDetected(mouseEvent -> {
+ Dragboard db = combineActionButton.startDragAndDrop(TransferMode.ANY);
+
+ ClipboardContent content = new ClipboardContent();
+
+ content.put(Action.getDataFormat(), createFakeAction(new CombineAction(), "Untitled Combine"));
+
+ db.setContent(content);
+
+ mouseEvent.consume();
+ });
+
+
+
+
+
+ vBox.getChildren().addAll(folderActionButton, combineActionButton);
+ vBox.setSpacing(5);
+
+ TitledPane pane = new TitledPane("StreamPi", vBox);
+
+ pluginsAccordion.getPanes().add(pane);
+ pluginsAccordion.setCache(true);
+ pluginsAccordion.setCacheHint(CacheHint.SPEED);
+ }
+
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/dashboard/actiondetailpane/ActionDetailsPane.java
@@ -0,0 +1,805 @@
+package com.stream_pi.server.window.dashboard.actiondetailpane;
+
+import com.stream_pi.actionapi.action.Action;
+import com.stream_pi.actionapi.action.ActionType;
+import com.stream_pi.actionapi.action.DisplayTextAlignment;
+import com.stream_pi.actionapi.action.Location;
+import com.stream_pi.actionapi.actionproperty.property.ControlType;
+import com.stream_pi.actionapi.actionproperty.property.Property;
+import com.stream_pi.actionapi.actionproperty.property.Type;
+import com.stream_pi.actionapi.otheractions.CombineAction;
+import com.stream_pi.actionapi.otheractions.FolderAction;
+import com.stream_pi.server.uipropertybox.UIPropertyBox;
+import com.stream_pi.server.client.Client;
+import com.stream_pi.server.client.ClientProfile;
+import com.stream_pi.server.connection.ClientConnection;
+import com.stream_pi.server.connection.ClientConnections;
+import com.stream_pi.server.window.dashboard.actiongridpane.ActionBox;
+import com.stream_pi.server.window.ExceptionAndAlertHandler;
+import com.stream_pi.util.exception.MinorException;
+import com.stream_pi.util.exception.SevereException;
+import com.stream_pi.util.uihelper.HBoxInputBox;
+import com.stream_pi.util.uihelper.HBoxInputBoxWithFileChooser;
+import com.stream_pi.util.uihelper.SpaceFiller;
+import javafx.application.HostServices;
+import javafx.collections.FXCollections;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.Node;
+import javafx.scene.control.*;
+import javafx.scene.input.TransferMode;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.Region;
+import javafx.scene.layout.VBox;
+import javafx.scene.paint.Color;
+import javafx.scene.paint.Paint;
+import javafx.stage.FileChooser;
+import javafx.stage.Window;
+import org.kordamp.ikonli.javafx.FontIcon;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.logging.Logger;
+
+public class ActionDetailsPane extends VBox implements ActionDetailsPaneListener {
+
+ private ScrollPane scrollPane;
+
+ private VBox vbox;
+ private VBox clientPropertiesVBox;
+
+ private Button saveButton;
+ private Button deleteButton;
+ private Button openFolderButton;
+
+ private HBox buttonBar;
+
+ private Label actionHeadingLabel;
+
+ private Logger logger;
+
+ private Button returnButtonForCombineActionChild;
+
+ private ExceptionAndAlertHandler exceptionAndAlertHandler;
+
+ private HostServices hostServices;
+
+ public ActionDetailsPane(ExceptionAndAlertHandler exceptionAndAlertHandler, HostServices hostServices) {
+ this.hostServices = hostServices;
+ this.exceptionAndAlertHandler = exceptionAndAlertHandler;
+
+ logger = Logger.getLogger(ActionDetailsPane.class.getName());
+
+ setSpacing(10.0);
+
+ // VBox.setVgrow(this, Priority.SOMETIMES);
+
+ clientPropertiesVBox = new VBox();
+ clientPropertiesVBox.setSpacing(10.0);
+
+ vbox = new VBox();
+ vbox.setPadding(new Insets(0, 25, 0, 5));
+ vbox.getStyleClass().add("action_details_pane_vbox");
+
+ vbox.setSpacing(10.0);
+
+ getStyleClass().add("action_details_pane");
+ // setPadding(new Insets(5,50,5,50));
+ // setMinHeight(245);
+
+ scrollPane = new ScrollPane();
+ VBox.setMargin(scrollPane, new Insets(0, 0, 0, 10));
+
+ scrollPane.getStyleClass().add("action_details_pane_scroll_pane");
+
+ setMinHeight(310);
+ scrollPane.setContent(vbox);
+
+ vbox.prefWidthProperty().bind(scrollPane.widthProperty());
+ scrollPane.prefWidthProperty().bind(widthProperty());
+
+ VBox.setVgrow(scrollPane, Priority.ALWAYS);
+
+ scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
+
+ openFolderButton = new Button("Open Folder");
+ FontIcon folderOpenIcon = new FontIcon("far-folder-open");
+ openFolderButton.setGraphic(folderOpenIcon);
+ openFolderButton.setOnAction(event -> onOpenFolderButtonClicked());
+
+ saveButton = new Button("Apply Changes");
+ FontIcon syncIcon = new FontIcon("fas-sync-alt");
+ saveButton.setGraphic(syncIcon);
+ saveButton.setOnAction(event -> onSaveButtonClicked());
+
+ deleteButton = new Button("Delete action");
+ FontIcon deleteIcon = new FontIcon("fas-trash");
+ deleteIcon.setIconColor(Paint.valueOf("#FF0000"));
+ deleteButton.setTextFill(Paint.valueOf("#FF0000"));
+ deleteButton.setGraphic(deleteIcon);
+
+ deleteButton.setOnAction(event -> onDeleteButtonClicked());
+
+ returnButtonForCombineActionChild = new Button("Return");
+ returnButtonForCombineActionChild.setGraphic(new FontIcon("fas-caret-left"));
+ returnButtonForCombineActionChild.managedProperty().bind(returnButtonForCombineActionChild.visibleProperty());
+ returnButtonForCombineActionChild.setOnAction(event -> {
+ try {
+ logger.info("@@## : " + action.getParent());
+ onActionClicked(getClientProfile().getActionByID(action.getParent()), getActionBox());
+ } catch (MinorException e) {
+ e.printStackTrace();
+ }
+ });
+
+ buttonBar = new HBox(openFolderButton, returnButtonForCombineActionChild, saveButton, deleteButton);
+ buttonBar.setPadding(new Insets(10, 10, 10, 0));
+ buttonBar.setAlignment(Pos.CENTER_RIGHT);
+ buttonBar.setVisible(false);
+ buttonBar.setSpacing(10.0);
+
+ actionHeadingLabel = new Label();
+
+ actionHeadingLabel.getStyleClass().add("action_details_pane_action_heading_label");
+
+ HBox headingHBox = new HBox(actionHeadingLabel);
+
+ headingHBox.setPadding(new Insets(5, 10, 0, 10));
+
+ getChildren().addAll(headingHBox, scrollPane, buttonBar);
+
+ displayTextAlignmentComboBox = new ComboBox<>(FXCollections.observableArrayList(DisplayTextAlignment.TOP,
+ DisplayTextAlignment.CENTER, DisplayTextAlignment.BOTTOM));
+
+ displayTextAlignmentComboBox.managedProperty().bind(displayTextAlignmentComboBox.visibleProperty());
+
+ actionClientProperties = new ArrayList<>();
+
+ displayNameTextField = new TextField();
+ displayNameTextField.managedProperty().bind(displayNameTextField.visibleProperty());
+
+ iconFileTextField = new TextField();
+ iconFileTextField.managedProperty().bind(iconFileTextField.visibleProperty());
+ iconFileTextField.textProperty().addListener((observableValue, s, t1) -> {
+ try {
+ if (!s.equals(t1) && t1.length() > 0) {
+ byte[] iconFileByteArray = Files.readAllBytes(new File(t1).toPath());
+
+ hideIconCheckBox.setDisable(false);
+ hideIconCheckBox.setSelected(false);
+ clearIconButton.setDisable(false);
+
+ System.out.println("ABABABABABBABABBABABABCCCCCCCCCCCCCCCCCC");
+
+ action.setIcon(iconFileByteArray);
+ setSendIcon(true);
+
+ System.out.println(action.getIconAsByteArray().length);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ exceptionAndAlertHandler.handleMinorException(new MinorException(e.getMessage()));
+ }
+ });
+
+ clearIconButton = new Button("Clear Icon");
+ clearIconButton.managedProperty().bind(clearIconButton.visibleProperty());
+ clearIconButton.setOnAction(event -> {
+
+ hideIconCheckBox.setDisable(true);
+ hideIconCheckBox.setSelected(false);
+
+ clearIconButton.setDisable(true);
+ iconFileTextField.clear();
+ });
+
+ hideDisplayTextCheckBox = new CheckBox("Hide");
+ hideDisplayTextCheckBox.managedProperty().bind(hideDisplayTextCheckBox.visibleProperty());
+
+ hideIconCheckBox = new CheckBox("Hide");
+ hideIconCheckBox.managedProperty().bind(hideIconCheckBox.visibleProperty());
+
+ actionBackgroundColourPicker = new ColorPicker();
+ actionBackgroundColourPicker.managedProperty().bind(actionBackgroundColourPicker.visibleProperty());
+
+ displayTextColourPicker = new ColorPicker();
+ displayTextColourPicker.managedProperty().bind(displayTextColourPicker.visibleProperty());
+
+ actionBackgroundColourTransparentCheckBox = new CheckBox("Default");
+ actionBackgroundColourPicker.disableProperty()
+ .bind(actionBackgroundColourTransparentCheckBox.selectedProperty());
+
+ HBox.setMargin(actionBackgroundColourTransparentCheckBox, new Insets(0, 0, 0, 10));
+
+
+ displayTextColourDefaultCheckBox = new CheckBox("Default");
+ displayTextColourPicker.disableProperty()
+ .bind(displayTextColourDefaultCheckBox.selectedProperty());
+
+ HBox.setMargin(displayTextColourDefaultCheckBox, new Insets(0, 0, 0, 10));
+
+ Region r = new Region();
+ HBox.setHgrow(r, Priority.ALWAYS);
+
+ Region r1 = new Region();
+ HBox.setHgrow(r1, Priority.ALWAYS);
+
+ HBox displayTextColourHBox = new HBox(new Label("Display Text Colour"), r1, displayTextColourPicker,
+ displayTextColourDefaultCheckBox);
+ displayTextColourHBox.setAlignment(Pos.CENTER);
+ displayTextColourHBox.setSpacing(5.0);
+
+ HBox bgColourHBox = new HBox(new Label("Background Colour"), r, actionBackgroundColourPicker,
+ actionBackgroundColourTransparentCheckBox);
+ bgColourHBox.setAlignment(Pos.CENTER);
+ bgColourHBox.setSpacing(5.0);
+
+ HBox clearIconHBox = new HBox(clearIconButton);
+ clearIconHBox.setAlignment(Pos.CENTER_RIGHT);
+
+ displayTextFieldHBox = new HBoxInputBox("Display Name", displayNameTextField, hideDisplayTextCheckBox);
+
+ normalActionsPropsVBox = new VBox(displayTextColourHBox,
+
+ new HBox(new Label("Alignment"), new SpaceFiller(SpaceFiller.FillerType.HBox),
+ displayTextAlignmentComboBox),
+
+ new HBoxInputBoxWithFileChooser("Icon", iconFileTextField, hideIconCheckBox,
+ new FileChooser.ExtensionFilter("Images", "*.jpeg", "*.jpg", "*.png", "*.gif")),
+
+ clearIconHBox, bgColourHBox);
+ normalActionsPropsVBox.managedProperty().bind(normalActionsPropsVBox.visibleProperty());
+ normalActionsPropsVBox.setSpacing(10.0);
+
+ vbox.getChildren().addAll(displayTextFieldHBox, normalActionsPropsVBox, clientPropertiesVBox);
+
+ vbox.setVisible(false);
+ scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
+
+ setOnDragOver(dragEvent -> {
+ if (dragEvent.getDragboard().hasContent(Action.getDataFormat()) && action != null) {
+ if (action.getActionType() == ActionType.COMBINE) {
+ dragEvent.acceptTransferModes(TransferMode.ANY);
+
+ dragEvent.consume();
+ }
+ }
+ });
+
+ setOnDragDropped(dragEvent -> {
+ try {
+ Action newAction = (Action) dragEvent.getDragboard().getContent(Action.getDataFormat());
+
+ if (newAction.getActionType() == ActionType.NORMAL) {
+ newAction.setLocation(new Location(-1, -1));
+
+ newAction.setParent(this.action.getID());
+
+ combineActionPropertiesPane.getCombineAction().addChild(newAction.getID());
+
+ addActionToCurrentClientProfile(newAction);
+
+ ClientConnection connection = ClientConnections.getInstance()
+ .getClientConnectionBySocketAddress(getClient().getRemoteSocketAddress());
+
+ connection.saveActionDetails(getClientProfile().getID(), newAction);
+
+ combineActionPropertiesPane.renderProps();
+
+ saveAction();
+ }
+ } catch (MinorException e) {
+ exceptionAndAlertHandler.handleMinorException(e);
+ e.printStackTrace();
+ } catch (SevereException e) {
+ exceptionAndAlertHandler.handleSevereException(e);
+ e.printStackTrace();
+ } catch (CloneNotSupportedException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+
+ private VBox normalActionsPropsVBox;
+
+ private HBox displayTextFieldHBox;
+
+ private Client client;
+ private ClientProfile clientProfile;
+
+ public void setClient(Client client) {
+ this.client = client;
+ }
+
+ public Client getClient() {
+ return client;
+ }
+
+ public void setClientProfile(ClientProfile clientProfile) {
+ this.clientProfile = clientProfile;
+ }
+
+ public ClientProfile getClientProfile() {
+ return clientProfile;
+ }
+
+ public void setActionHeadingLabelText(String text) {
+ actionHeadingLabel.setText(text);
+ }
+
+ private Action action;
+
+ public Action getAction() {
+ return action;
+ }
+
+ private ActionBox actionBox;
+
+ public ActionBox getActionBox() {
+ return actionBox;
+ }
+
+ @Override
+ public void onActionClicked(Action action, ActionBox actionBox) throws MinorException {
+ this.action = action;
+ this.actionBox = actionBox;
+
+ System.out.println(action.getActionType());
+
+
+ logger.info("action Display text : "+action.getDisplayText());
+ clear();
+
+ renderActionProperties();
+ }
+
+ private TextField displayNameTextField;
+ private CheckBox hideDisplayTextCheckBox;
+ private CheckBox hideIconCheckBox;
+ private TextField iconFileTextField;
+ private Button clearIconButton;
+ private ColorPicker actionBackgroundColourPicker;
+ private ColorPicker displayTextColourPicker;
+ private CheckBox actionBackgroundColourTransparentCheckBox;
+ private CheckBox displayTextColourDefaultCheckBox;
+ private ComboBox<DisplayTextAlignment> displayTextAlignmentComboBox;
+
+ public void clear()
+ {
+ sendIcon = false;
+ actionClientProperties.clear();
+ displayNameTextField.clear();
+ iconFileTextField.clear();
+ clientPropertiesVBox.getChildren().clear();
+ vbox.setVisible(false);
+ scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
+ buttonBar.setVisible(false);
+ setActionHeadingLabelText("");
+
+ actionBackgroundColourPicker.setValue(Color.WHITE);
+ displayTextColourPicker.setValue(Color.WHITE);
+ }
+
+ boolean isCombineChild = false;
+
+ public boolean isCombineChild() {
+ return isCombineChild;
+ }
+
+ public void renderActionProperties() throws MinorException
+ {
+
+ if(action.getLocation().getCol() == -1) //Combine Child action
+ isCombineChild = true;
+ else
+ isCombineChild = false;
+
+ displayNameTextField.setText(action.getDisplayText());
+
+ System.out.println(action.getDisplayText()+"@@@@::::"+isCombineChild);
+
+ if(isCombineChild)
+ {
+ setReturnButtonForCombineActionChildVisible(true);
+ normalActionsPropsVBox.setVisible(false);
+ hideDisplayTextCheckBox.setSelected(false);
+ hideDisplayTextCheckBox.setVisible(false);
+ }
+ else
+ {
+ normalActionsPropsVBox.setVisible(true);
+ setReturnButtonForCombineActionChildVisible(false);
+ hideDisplayTextCheckBox.setVisible(true);
+ setFolderButtonVisible(action.getActionType().equals(ActionType.FOLDER));
+
+ displayTextAlignmentComboBox.getSelectionModel().select(action.getDisplayTextAlignment());
+
+ if(!action.getBgColourHex().isEmpty())
+ actionBackgroundColourPicker.setValue(Color.valueOf(action.getBgColourHex()));
+ else
+ actionBackgroundColourTransparentCheckBox.setSelected(true);
+
+
+
+ if(!action.getDisplayTextFontColourHex().isEmpty())
+ displayTextColourPicker.setValue(Color.valueOf(action.getDisplayTextFontColourHex()));
+ else
+ displayTextColourDefaultCheckBox.setSelected(true);
+
+
+ hideDisplayTextCheckBox.setSelected(!action.isShowDisplayText());
+
+
+ hideIconCheckBox.setDisable(!action.isHasIcon());
+
+ hideIconCheckBox.setSelected(!action.isShowIcon());
+
+ if(!action.isHasIcon())
+ {
+ hideIconCheckBox.setSelected(false);
+ }
+
+ clearIconButton.setDisable(!action.isHasIcon());
+ }
+
+
+
+ buttonBar.setVisible(true);
+ vbox.setVisible(true);
+ scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
+
+ if(action.getActionType() == ActionType.NORMAL)
+ {
+ if(action.isInvalid())
+ setActionHeadingLabelText("Invalid action ("+action.getModuleName()+")");
+ else
+ setActionHeadingLabelText(action.getName());
+ }
+ else if(action.getActionType() == ActionType.COMBINE)
+ setActionHeadingLabelText("Combine action");
+ else if(action.getActionType() == ActionType.FOLDER)
+ setActionHeadingLabelText("Folder action");
+
+
+ if(!action.isInvalid())
+ {
+ if(action.getActionType() == ActionType.NORMAL)
+ renderClientProperties();
+ else if(action.getActionType() == ActionType.COMBINE)
+ renderCombineActionProperties();
+ }
+ }
+
+ private CombineActionPropertiesPane combineActionPropertiesPane;
+
+ public CombineActionPropertiesPane getCombineActionPropertiesPane() {
+ return combineActionPropertiesPane;
+ }
+
+ public void setReturnButtonForCombineActionChildVisible(boolean visible)
+ {
+ returnButtonForCombineActionChild.setVisible(visible);
+ }
+
+ public void renderCombineActionProperties()
+ {
+ try {
+ logger.info("@@@@@ : "+action.getClientProperties().getSize());
+ combineActionPropertiesPane = new CombineActionPropertiesPane(getActionAsCombineAction(action),
+ getClientProfile(),
+ this
+ );
+
+ clientPropertiesVBox.getChildren().add(combineActionPropertiesPane);
+ }
+ catch (MinorException e)
+ {
+ e.printStackTrace();
+ exceptionAndAlertHandler.handleMinorException(e);
+ }
+ }
+
+ public void setAction(Action action) {
+ this.action = action;
+ }
+
+ public FolderAction getActionAsFolderAction(Action action)
+ {
+ FolderAction folderAction = new FolderAction();
+ folderAction.setDisplayText(action.getDisplayText());
+ folderAction.setName(action.getName());
+ folderAction.setID(action.getID());
+ folderAction.setLocation(action.getLocation());
+ folderAction.setBgColourHex(action.getBgColourHex());
+ folderAction.setParent(action.getParent());
+ folderAction.getClientProperties().set(action.getClientProperties());
+ folderAction.setDisplayTextAlignment(action.getDisplayTextAlignment());
+ folderAction.setShowIcon(action.isShowIcon());
+ folderAction.setHasIcon(action.isHasIcon());
+ if(folderAction.isHasIcon())
+ folderAction.setIcon(action.getIconAsByteArray());
+ folderAction.setDisplayTextFontColourHex(action.getDisplayTextFontColourHex());
+
+ return folderAction;
+ }
+
+ public CombineAction getActionAsCombineAction(Action action)
+ {
+ CombineAction combineAction = new CombineAction();
+ combineAction.setDisplayText(action.getDisplayText());
+ combineAction.setName(action.getName());
+ combineAction.setID(action.getID());
+ combineAction.setLocation(action.getLocation());
+ combineAction.setBgColourHex(action.getBgColourHex());
+ combineAction.setParent(action.getParent());
+ combineAction.getClientProperties().set(action.getClientProperties());
+ combineAction.setDisplayTextAlignment(action.getDisplayTextAlignment());
+ combineAction.setShowIcon(action.isShowIcon());
+ combineAction.setHasIcon(action.isHasIcon());
+ if(combineAction.isHasIcon())
+ combineAction.setIcon(action.getIconAsByteArray());
+ combineAction.setDisplayTextFontColourHex(action.getDisplayTextFontColourHex());
+
+ for(Property prop : combineAction.getClientProperties().get())
+ {
+ System.out.println("PROP : "+prop.getName()+","+prop.getRawValue());
+ }
+ return combineAction;
+ }
+
+ public void onOpenFolderButtonClicked()
+ {
+ FolderAction folderAction = getActionAsFolderAction(action);
+ actionBox.getActionGridPaneListener().renderFolder(folderAction);
+ clear();
+ }
+
+ @Override
+ public Window getCurrentWindow() {
+ return getScene().getWindow();
+ }
+
+ private ArrayList<UIPropertyBox> actionClientProperties;
+
+ public void renderClientProperties() throws MinorException
+ {
+ for(int i =0;i< action.getClientProperties().getSize(); i++)
+ {
+ Property eachProperty = action.getClientProperties().get().get(i);
+
+ if(!eachProperty.isVisible())
+ continue;
+
+ Label label = new Label(eachProperty.getDisplayName());
+
+ HBox hBox = new HBox(label);
+ hBox.setSpacing(5.0);
+ hBox.setAlignment(Pos.CENTER_LEFT);
+
+ Node controlNode = null;
+
+ if(eachProperty.getHelpLink() != null)
+ {
+ Button helpButton = new Button();
+ FontIcon questionIcon = new FontIcon("fas-question");
+ helpButton.setGraphic(questionIcon);
+
+ helpButton.setOnAction(event -> {
+ hostServices.showDocument(eachProperty.getHelpLink());
+ });
+
+ hBox.getChildren().add(helpButton);
+ }
+
+ hBox.getChildren().add(new SpaceFiller(SpaceFiller.FillerType.HBox));
+
+ if(eachProperty.getControlType() == ControlType.COMBO_BOX)
+ {
+ ComboBox<String> comboBox = new ComboBox<>();
+ comboBox.getItems().addAll(eachProperty.getListValue());
+ comboBox.getSelectionModel().select(eachProperty.getSelectedIndex());
+
+
+ controlNode = comboBox;
+ }
+ else if(eachProperty.getControlType() == ControlType.TEXT_FIELD)
+ {
+ TextField textField = new TextField(eachProperty.getRawValue());
+
+ controlNode= textField;
+ }
+ else if(eachProperty.getControlType() == ControlType.TOGGLE)
+ {
+ ToggleButton toggleButton = new ToggleButton();
+ toggleButton.setSelected(eachProperty.getBoolValue());
+
+ if(eachProperty.getBoolValue())
+ toggleButton.setText("ON");
+ else
+ toggleButton.setText("OFF");
+
+ toggleButton.selectedProperty().addListener((observableValue, aBoolean, t1) -> {
+ if(t1)
+ toggleButton.setText("ON");
+ else
+ toggleButton.setText("OFF");
+ });
+
+ controlNode = toggleButton;
+ }
+ else if(eachProperty.getControlType() == ControlType.SLIDER_DOUBLE)
+ {
+ Slider slider = new Slider();
+ slider.setValue(eachProperty.getDoubleValue());
+ slider.setMax(eachProperty.getMaxDoubleValue());
+ slider.setMin(eachProperty.getMinDoubleValue());
+
+ controlNode = slider;
+ }
+ else if(eachProperty.getControlType() == ControlType.SLIDER_INTEGER)
+ {
+ Slider slider = new Slider();
+ slider.setValue(eachProperty.getIntValue());
+
+ slider.setMax(eachProperty.getMaxIntValue());
+ slider.setMin(eachProperty.getMinIntValue());
+ slider.setBlockIncrement(1.0);
+ slider.setSnapToTicks(true);
+
+ controlNode = slider;
+ }
+
+
+ hBox.getChildren().add(controlNode);
+
+ UIPropertyBox clientProperty = new UIPropertyBox(i, eachProperty.getDisplayName(), controlNode,
+ eachProperty.getControlType(), eachProperty.getType(), eachProperty.isCanBeBlank());
+
+ actionClientProperties.add(clientProperty);
+
+ clientPropertiesVBox.getChildren().add(hBox);
+ }
+ }
+
+ public void onSaveButtonClicked()
+ {
+ try {
+ // saveButton.setDisable(true);
+ // deleteButton.setDisable(true);
+
+ validateForm();
+
+ saveAction();
+ }
+ catch (MinorException e)
+ {
+ exceptionAndAlertHandler.handleMinorException(e);
+ }
+
+ }
+
+ private boolean sendIcon = false;
+
+ @Override
+ public void setSendIcon(boolean sendIcon)
+ {
+ this.sendIcon = sendIcon;
+ }
+
+ public void addActionToCurrentClientProfile(Action newAction) throws CloneNotSupportedException {
+ getClientProfile().addAction(newAction);
+ }
+
+ @Override
+ public void saveAction(Action action, boolean runAsync)
+ {
+ new OnSaveActionTask(
+ ClientConnections.getInstance().getClientConnectionBySocketAddress(
+ getClient().getRemoteSocketAddress()
+ ),
+ action,
+ displayNameTextField.getText(),
+ isCombineChild(),
+ !hideDisplayTextCheckBox.isSelected(),
+ displayTextColourDefaultCheckBox.isSelected(),
+ "#" + displayTextColourPicker.getValue().toString().substring(2),
+ clearIconButton.isDisable(),
+ !hideIconCheckBox.isSelected(),
+ displayTextAlignmentComboBox.getSelectionModel().getSelectedItem(),
+ actionBackgroundColourTransparentCheckBox.isSelected(),
+ "#" + actionBackgroundColourPicker.getValue().toString().substring(2),
+ getCombineActionPropertiesPane(),
+ clientProfile, sendIcon, actionBox, actionClientProperties, exceptionAndAlertHandler,
+ saveButton, deleteButton, runAsync
+ );
+ }
+
+ @Override
+ public void saveAction()
+ {
+ saveAction(action, true);
+ }
+
+ public void setFolderButtonVisible(boolean visible)
+ {
+ openFolderButton.setVisible(visible);
+ }
+
+ public void validateForm() throws MinorException
+ {
+ String displayNameStr = displayNameTextField.getText();
+
+ StringBuilder finalErrors = new StringBuilder();
+
+ if(displayNameStr.isBlank())
+ {
+ finalErrors.append(" * Display Name cannot be blank\n");
+ }
+
+ if(!isCombineChild())
+ {
+ if(action.isHasIcon())
+ {
+ if(hideDisplayTextCheckBox.isSelected() && hideIconCheckBox.isSelected())
+ finalErrors.append(" * Both Icon and display text check box cannot be hidden.\n");
+ }
+ else
+ {
+ if(hideDisplayTextCheckBox.isSelected())
+ finalErrors.append(" * Display Text cannot be hidden, since there is also no icon.\n");
+ }
+
+ }
+
+
+
+ for (UIPropertyBox clientProperty : actionClientProperties) {
+
+ Node controlNode = clientProperty.getControlNode();
+
+ if (clientProperty.getControlType() == ControlType.TEXT_FIELD)
+ {
+ String value = ((TextField) controlNode).getText();
+ if(clientProperty.getType() == Type.INTEGER)
+ {
+ try
+ {
+ Integer.parseInt(value);
+ }
+ catch (NumberFormatException e)
+ {
+ finalErrors.append(" -> ").append(clientProperty.getDisplayName()).append(" must be integer.\n");
+ }
+ }
+ else
+ {
+ if(value.isBlank() && !clientProperty.isCanBeBlank())
+ finalErrors.append(" -> ").append(clientProperty.getDisplayName()).append(" cannot be blank.\n");
+ }
+ }
+ }
+
+
+ if(!finalErrors.toString().isEmpty())
+ {
+ throw new MinorException("You made mistakes",
+ finalErrors.toString());
+ }
+ }
+
+ public void onDeleteButtonClicked()
+ {
+ new OnDeleteActionTask(
+ ClientConnections.getInstance().getClientConnectionBySocketAddress(
+ getClient().getRemoteSocketAddress()
+ ),
+ action,
+ isCombineChild(),
+ getCombineActionPropertiesPane(),
+ clientProfile, actionBox, this, exceptionAndAlertHandler,
+ !isCombineChild
+ );
+ }
+}
\ No newline at end of file
A
src/main/java/com/stream_pi/server/window/dashboard/actiondetailpane/ActionDetailsPaneListener.java
+23
−0
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/dashboard/actiondetailpane/ActionDetailsPaneListener.java
@@ -0,0 +1,23 @@
+package com.stream_pi.server.window.dashboard.actiondetailpane;
+
+import com.stream_pi.actionapi.action.Action;
+import com.stream_pi.server.window.dashboard.actiongridpane.ActionBox;
+import com.stream_pi.util.exception.MinorException;
+import javafx.stage.Window;
+
+public interface ActionDetailsPaneListener {
+ void onActionClicked(Action action, ActionBox actionBox) throws MinorException;
+
+ void saveAction();
+
+ void saveAction(Action action, boolean runAsync);
+
+ void clear();
+
+ void setSendIcon(boolean sendIcon);
+
+ void onOpenFolderButtonClicked();
+
+ Window getCurrentWindow();
+
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/dashboard/actiondetailpane/CombineActionPropertiesPane.java
@@ -0,0 +1,174 @@
+package com.stream_pi.server.window.dashboard.actiondetailpane;
+
+import com.stream_pi.actionapi.action.Action;
+import com.stream_pi.actionapi.actionproperty.property.Property;
+import com.stream_pi.actionapi.otheractions.CombineAction;
+import com.stream_pi.server.client.ClientProfile;
+import com.stream_pi.util.exception.MinorException;
+import javafx.event.ActionEvent;
+import javafx.geometry.Insets;
+import javafx.scene.Node;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.Region;
+import javafx.scene.layout.VBox;
+import org.kordamp.ikonli.javafx.FontIcon;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CombineActionPropertiesPane extends VBox {
+ private CombineAction combineAction;
+ private ClientProfile clientProfile;
+ private ActionDetailsPane actionDetailsPane;
+
+ public CombineAction getCombineAction() {
+ return combineAction;
+ }
+
+ public CombineActionPropertiesPane(CombineAction combineAction, ClientProfile clientProfile, ActionDetailsPane actionDetailsPane) throws MinorException {
+ this.combineAction = combineAction;
+ this.clientProfile = clientProfile;
+ this.actionDetailsPane = actionDetailsPane;
+
+ setSpacing(10.0);
+
+ setPadding(new Insets(0,0,10,0));
+
+ renderProps();
+ }
+
+
+ public void renderProps() throws MinorException {
+
+ getChildren().clear();
+
+ int i = 0;
+
+ for(String actionID : combineAction.getChildrenIDSequential())
+ {
+ Action action = clientProfile.getActionByID(actionID);
+
+ System.out.println("232323xxxxxxxxxxxx : "+action.getID());
+
+ Button settingsButton = new Button();
+
+ FontIcon settingsFontIcon = new FontIcon("fas-cog");
+ settingsButton.setGraphic(settingsFontIcon);
+
+
+ settingsButton.setOnAction(event -> onSettingsButtonClicked(action));
+
+ Button upButton = new Button();
+ FontIcon upButtonFontIcon = new FontIcon("fas-chevron-up");
+ upButton.setGraphic(upButtonFontIcon);
+
+
+ Button downButton = new Button();
+ FontIcon downButtonFontIcon = new FontIcon("fas-chevron-down");
+ downButton.setGraphic(downButtonFontIcon);
+
+ Label displayTextLabel = new Label(action.getDisplayText());
+ displayTextLabel.setId(action.getID());
+
+ Region r = new Region();
+ HBox.setHgrow(r, Priority.ALWAYS);
+
+ HBox actionHBox = new HBox(displayTextLabel, r, settingsButton, upButton, downButton);
+ actionHBox.setSpacing(5.0);
+
+ upButton.setUserData(i);
+ downButton.setUserData(i);
+
+
+ upButton.setOnAction(this::onUpButtonClicked);
+
+ downButton.setOnAction(this::onDownButtonClicked);
+
+ System.out.println("67878678678678");
+ getChildren().add(actionHBox);
+ System.out.println("9mhmmn");
+ i++;
+ }
+ }
+
+ public void onSettingsButtonClicked(Action action)
+ {
+ actionDetailsPane.clear();
+ actionDetailsPane.setAction(action);
+ try {
+ actionDetailsPane.renderActionProperties();
+ } catch (MinorException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void onUpButtonClicked(ActionEvent event) {
+ try {
+ Node node = (Node) event.getSource();
+
+ int currentIndex = (int) node.getUserData();
+
+ if(currentIndex > 0)
+ {
+
+ Property current = combineAction.getClientProperties().getSingleProperty(currentIndex+"");
+ Property aboveOne = combineAction.getClientProperties().getSingleProperty((currentIndex-1)+"");
+
+ combineAction.addChild(current.getRawValue(), currentIndex-1);
+ combineAction.addChild(aboveOne.getRawValue(), currentIndex);
+
+ actionDetailsPane.saveAction();
+ renderProps();
+ }
+ }
+ catch (MinorException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+
+ public void onDownButtonClicked(ActionEvent event)
+ {
+ try {
+ Node node = (Node) event.getSource();
+
+ int currentIndex = (int) node.getUserData();
+
+ if(currentIndex < getChildren().size() - 1)
+ {
+
+ Property current = combineAction.getClientProperties().getSingleProperty(currentIndex+"");
+ Property belowOne = combineAction.getClientProperties().getSingleProperty((currentIndex+1)+"");
+
+ combineAction.addChild(current.getRawValue(), currentIndex+1);
+ combineAction.addChild(belowOne.getRawValue(), currentIndex);
+
+ actionDetailsPane.saveAction();
+ renderProps();
+ }
+ }
+ catch (MinorException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+
+ public List<String> getFinalChildren()
+ {
+ ArrayList<String> children = new ArrayList<>();
+
+ for(int i = 0;i<getChildren().size();i++)
+ {
+ HBox hBox = (HBox) getChildren().get(i);
+ Label label = (Label) hBox.getChildren().get(0);
+ children.add(label.getId());
+ }
+
+ return children;
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/dashboard/actiondetailpane/OnDeleteActionTask.java
@@ -0,0 +1,120 @@
+package com.stream_pi.server.window.dashboard.actiondetailpane;
+
+import java.util.logging.Logger;
+
+import com.stream_pi.actionapi.action.Action;
+import com.stream_pi.server.client.ClientProfile;
+import com.stream_pi.server.connection.ClientConnection;
+import com.stream_pi.server.window.ExceptionAndAlertHandler;
+import com.stream_pi.server.window.dashboard.actiongridpane.ActionBox;
+
+import com.stream_pi.util.exception.MinorException;
+import com.stream_pi.util.exception.SevereException;
+import javafx.application.Platform;
+import javafx.concurrent.Task;
+
+public class OnDeleteActionTask extends Task<Void>
+{
+ private Logger logger;
+
+ public OnDeleteActionTask(ClientConnection connection, Action action, boolean isCombineChild,
+ CombineActionPropertiesPane combineActionPropertiesPane, ClientProfile clientProfile, ActionBox actionBox,
+ ActionDetailsPane actionDetailsPane,
+ ExceptionAndAlertHandler exceptionAndAlertHandler, boolean runAsync)
+ {
+ this.connection = connection;
+ this.action = action;
+ this.isCombineChild = isCombineChild;
+ this.combineActionPropertiesPane = combineActionPropertiesPane;
+ this.clientProfile = clientProfile;
+ this.actionBox = actionBox;
+ this.actionDetailsPane = actionDetailsPane;
+ this.exceptionAndAlertHandler = exceptionAndAlertHandler;
+
+ logger = Logger.getLogger(getClass().getName());
+
+ if(runAsync)
+ new Thread(this).start();
+ else
+ runTask();
+ }
+
+ private ClientConnection connection;
+ private Action action;
+ private ActionBox actionBox;
+ private ActionDetailsPane actionDetailsPane;
+ private boolean isCombineChild;
+ private ClientProfile clientProfile;
+ private CombineActionPropertiesPane combineActionPropertiesPane;
+ private ExceptionAndAlertHandler exceptionAndAlertHandler;
+
+
+ private void runTask()
+ {
+ try {
+
+ connection.deleteAction(clientProfile.getID(), action.getID());
+ clientProfile.removeActionByID(action.getID());
+
+ if(isCombineChild)
+ {
+ System.out.println("ACTION ID TO BE REMOVED : "+action.getID());
+ combineActionPropertiesPane.getCombineAction().removeChild(action.getID());
+
+ System.out.println("222155 "+combineActionPropertiesPane.getCombineAction().getClientProperties().getSize());
+
+ combineActionPropertiesPane.renderProps();
+
+ try {
+
+
+ actionDetailsPane.saveAction(combineActionPropertiesPane.getCombineAction(), false);
+
+ System.out.println(combineActionPropertiesPane.getCombineAction().getDisplayText()+"@#@#@#@#@#@#");
+ actionDetailsPane.onActionClicked(
+ combineActionPropertiesPane.getCombineAction(),
+ actionBox
+ );
+
+
+
+ } catch (MinorException e) {
+ e.printStackTrace();
+ }
+ }
+ else
+ {
+ Platform.runLater(()->{
+ actionBox.clear();
+ actionDetailsPane.clear();
+ });
+ }
+
+
+ // Platform.runLater(()->{
+ // saveButton.setDisable(false);
+ // deleteButton.setDisable(false);
+ // });
+
+ }
+ catch (SevereException e)
+ {
+ e.printStackTrace();
+ exceptionAndAlertHandler.handleSevereException(e);
+ }
+ catch (MinorException e)
+ {
+ e.printStackTrace();
+ exceptionAndAlertHandler.handleMinorException(e);
+ }
+ }
+
+
+ @Override
+ protected Void call() throws Exception
+ {
+ runTask();
+ return null;
+ }
+
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/dashboard/actiondetailpane/OnSaveActionTask.java
@@ -0,0 +1,233 @@
+package com.stream_pi.server.window.dashboard.actiondetailpane;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import com.stream_pi.actionapi.action.Action;
+import com.stream_pi.actionapi.action.ActionType;
+import com.stream_pi.actionapi.action.DisplayTextAlignment;
+import com.stream_pi.actionapi.actionproperty.ClientProperties;
+import com.stream_pi.actionapi.actionproperty.property.Property;
+import com.stream_pi.actionapi.actionproperty.property.Type;
+import com.stream_pi.server.client.ClientProfile;
+import com.stream_pi.server.connection.ClientConnection;
+import com.stream_pi.server.uipropertybox.UIPropertyBox;
+import com.stream_pi.server.window.ExceptionAndAlertHandler;
+import com.stream_pi.server.window.dashboard.actiongridpane.ActionBox;
+
+import com.stream_pi.util.exception.SevereException;
+import javafx.application.Platform;
+import javafx.concurrent.Task;
+import javafx.scene.control.Button;
+
+public class OnSaveActionTask extends Task<Void>
+{
+
+ private Logger logger;
+
+
+ public OnSaveActionTask(ClientConnection connection, Action action, String displayNameText, boolean isCombineChild,
+ boolean isShowDisplayText, boolean isDefaultDisplayTextColour, String displayTextFontColour, boolean isClearIcon,
+ boolean isHideIcon, DisplayTextAlignment displayTextAlignment, boolean isTransparentBackground, String backgroundColour,
+ CombineActionPropertiesPane combineActionPropertiesPane, ClientProfile clientProfile, boolean sendIcon, ActionBox actionBox,
+ ArrayList<UIPropertyBox> actionClientProperties, ExceptionAndAlertHandler exceptionAndAlertHandler, Button saveButton, Button deleteButton,
+ boolean runAsync)
+ {
+ this.saveButton = saveButton;
+ this.deleteButton = deleteButton;
+
+ this.connection = connection;
+ this.action = action;
+ this.displayNameText = displayNameText;
+ this.isCombineChild = isCombineChild;
+ this.isShowDisplayText = isShowDisplayText;
+ this.isDefaultDisplayTextColour = isDefaultDisplayTextColour;
+ this.displayTextFontColour = displayTextFontColour;
+ this.isClearIcon = isClearIcon;
+ this.isHideIcon = isHideIcon;
+ this.displayTextAlignment = displayTextAlignment;
+ this.isTransparentBackground = isTransparentBackground;
+ this.combineActionPropertiesPane = combineActionPropertiesPane;
+ this.clientProfile = clientProfile;
+ this.sendIcon = sendIcon;
+ this.actionBox = actionBox;
+ this.exceptionAndAlertHandler = exceptionAndAlertHandler;
+ this.backgroundColour = backgroundColour;
+ this.actionClientProperties = actionClientProperties;
+
+
+ logger = Logger.getLogger(getClass().getName());
+
+
+ if(runAsync)
+ new Thread(this).start();
+ else
+ runTask();
+ }
+
+ private Button saveButton;
+ private Button deleteButton;
+ private boolean isShowDisplayText;
+ private boolean isCombineChild;
+ private String displayNameText;
+ private boolean isDefaultDisplayTextColour;
+ private ArrayList<UIPropertyBox> actionClientProperties;
+ private String displayTextFontColour;
+ private boolean isClearIcon;
+ private boolean isHideIcon;
+ private DisplayTextAlignment displayTextAlignment;
+ private boolean isTransparentBackground;
+ private String backgroundColour;
+ private CombineActionPropertiesPane combineActionPropertiesPane;
+ private ClientProfile clientProfile;
+ private boolean sendIcon;
+ private ActionBox actionBox;
+ private ExceptionAndAlertHandler exceptionAndAlertHandler;
+ private Action action;
+ private ClientConnection connection;
+
+ private void setSaveDeleteButtonState(boolean state)
+ {
+ Platform.runLater(()->{
+ saveButton.setDisable(state);
+ deleteButton.setDisable(state);
+ });
+ }
+
+
+ private void runTask()
+ {
+ action.setDisplayText(displayNameText);
+
+ if(!isCombineChild)
+ {
+ setSaveDeleteButtonState(true);
+
+ action.setShowDisplayText(isShowDisplayText);
+
+ if(isDefaultDisplayTextColour)
+ action.setDisplayTextFontColourHex("");
+ else
+ {
+ action.setDisplayTextFontColourHex(displayTextFontColour);
+ //String fontColour = "#" + displayTextColourPicker.getValue().toString().substring(2);
+ //action.setDisplayTextFontColourHex(fontColour);
+ }
+
+
+ if(isClearIcon)
+ {
+ action.setIcon(null);
+ action.setHasIcon(false);
+ action.setShowIcon(false);
+ }
+
+ if(action.isHasIcon())
+ action.setShowIcon(isHideIcon);
+
+
+ action.setDisplayTextAlignment(displayTextAlignment);
+
+
+ logger.info("BBBGGG : "+backgroundColour);
+ if(isTransparentBackground)
+ action.setBgColourHex("");
+ else
+ {
+ //String bgColour = "#" + actionBackgroundColourPicker.getValue().toString().substring(2);
+ action.setBgColourHex(backgroundColour);
+ }
+ }
+
+ System.out.println("parent : "+action.getParent());
+
+
+ if(action.getActionType() == ActionType.COMBINE)
+ {
+ List<String> finalChildren = combineActionPropertiesPane.getFinalChildren();
+ System.out.println("2334 "+finalChildren.size());
+
+ ClientProperties clientProperties = new ClientProperties();
+
+ for(int i = 0;i<finalChildren.size();i++)
+ {
+ Property property = new Property(i+"", Type.STRING);
+ property.setRawValue(finalChildren.get(i));
+
+ clientProperties.addProperty(property);
+ }
+
+ action.getClientProperties().set(clientProperties);
+ }
+ else
+ {
+ //properties
+ for (UIPropertyBox clientProperty : actionClientProperties) {
+ action.getClientProperties().get().get(clientProperty.getIndex()).setRawValue(clientProperty.getRawValue());
+ }
+ }
+
+
+ try
+ {
+ logger.info("Saving action ... "+action.isHasIcon()+"+"+sendIcon);
+
+ /*if(action.isHasIcon())
+ {
+ if(clientProfile.getActionByID(action.getID()).getIconAsByteArray() == null)
+ {
+ sendIcon = true;
+ }
+ else
+ {
+ if(!Arrays.equals(action.getIconAsByteArray(), clientProfile.getActionByID(action.getID()).getIconAsByteArray()))
+ {
+ logger.info("Sending ...");
+ sendIcon = true;
+ }
+ }
+ }*/
+
+ connection.saveActionDetails(clientProfile.getID(), action);
+
+ if(sendIcon)
+ {
+ connection.sendIcon(clientProfile.getID(), action.getID(), action.getIconAsByteArray());
+ }
+
+ if(!isCombineChild)
+ {
+ Platform.runLater(()->{
+ actionBox.clear();
+ actionBox.setAction(action);
+ actionBox.baseInit();
+ actionBox.init();
+ });
+
+ setSaveDeleteButtonState(false);
+ }
+
+ clientProfile.removeActionByID(action.getID());
+ clientProfile.addAction(action);
+
+ }
+ catch (SevereException e)
+ {
+ e.printStackTrace();
+ exceptionAndAlertHandler.handleSevereException(e);
+ }
+ catch (CloneNotSupportedException e)
+ {
+ e.printStackTrace();
+ }
+
+ }
+
+ @Override
+ protected Void call() throws Exception
+ {
+ runTask();
+ return null;
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/dashboard/actiongridpane/ActionBox.java
@@ -0,0 +1,349 @@
+package com.stream_pi.server.window.dashboard.actiongridpane;
+
+import com.stream_pi.actionapi.action.Action;
+import com.stream_pi.actionapi.action.ActionType;
+import com.stream_pi.actionapi.action.DisplayTextAlignment;
+import com.stream_pi.actionapi.action.Location;
+import com.stream_pi.server.window.ExceptionAndAlertHandler;
+import com.stream_pi.server.window.dashboard.actiondetailpane.ActionDetailsPaneListener;
+import com.stream_pi.util.exception.MinorException;
+import javafx.application.Platform;
+import javafx.geometry.Pos;
+import javafx.scene.CacheHint;
+import javafx.scene.control.Label;
+import javafx.scene.image.Image;
+import javafx.scene.input.ClipboardContent;
+import javafx.scene.input.Dragboard;
+import javafx.scene.input.MouseButton;
+import javafx.scene.input.TransferMode;
+import javafx.scene.layout.Background;
+import javafx.scene.layout.BackgroundImage;
+import javafx.scene.layout.BackgroundPosition;
+import javafx.scene.layout.BackgroundRepeat;
+import javafx.scene.layout.BackgroundSize;
+import javafx.scene.layout.StackPane;
+import javafx.scene.text.TextAlignment;
+
+import java.io.ByteArrayInputStream;
+import java.io.ObjectInputStream;
+import java.nio.ByteBuffer;
+
+public class ActionBox extends StackPane{
+
+ private Label displayTextLabel;
+
+ private int row;
+ private int col;
+
+ public void setRow(int row) {
+ this.row = row;
+ }
+
+ public void setCol(int col) {
+ this.col = col;
+ }
+
+ public int getRow() {
+ return row;
+ }
+
+ public int getCol() {
+ return col;
+ }
+
+ private ActionDetailsPaneListener actionDetailsPaneListener;
+
+ public void clear()
+ {
+ setAction(null);
+ setInvalid(false);
+ setBackground(Background.EMPTY);
+ setStyle(null);
+ getChildren().clear();
+ }
+
+ public void baseInit()
+ {
+
+ displayTextLabel = new Label();
+ displayTextLabel.setWrapText(true);
+ displayTextLabel.setTextAlignment(TextAlignment.CENTER);
+ displayTextLabel.getStyleClass().add("action_box_display_text_label");
+
+ displayTextLabel.prefHeightProperty().bind(heightProperty());
+ displayTextLabel.prefWidthProperty().bind(widthProperty());
+
+
+ getChildren().addAll(displayTextLabel);
+
+ setMinSize(size, size);
+ setMaxSize(size, size);
+
+ getStyleClass().add("action_box");
+ getStyleClass().add("action_box_icon_not_present");
+ getStyleClass().add("action_box_valid");
+
+
+ setOnDragOver(dragEvent ->
+ {
+ if(dragEvent.getDragboard().hasContent(Action.getDataFormat()))
+ {
+ dragEvent.acceptTransferModes(TransferMode.ANY);
+
+ dragEvent.consume();
+ }
+ });
+
+ setOnDragDropped(dragEvent ->
+ {
+ try
+ {
+ if(action == null)
+ {
+ Action action = (Action) dragEvent.getDragboard().getContent(Action.getDataFormat());
+
+ action.setLocation(new Location(getRow(),
+ getCol()));
+
+ action.setParent(getStreamPiParent());
+
+ action.setIDRandom();
+
+
+ actionGridPaneListener.addActionToCurrentClientProfile(action);
+
+ setAction(action);
+ init();
+
+
+ actionDetailsPaneListener.onActionClicked(action, this);
+
+ if(action.isHasIcon())
+ actionDetailsPaneListener.setSendIcon(true);
+
+ actionDetailsPaneListener.saveAction();
+ }
+ }
+ catch (MinorException e)
+ {
+ exceptionAndAlertHandler.handleMinorException(e);
+ e.printStackTrace();
+ }
+ });
+
+ setOnDragDetected(mouseEvent -> {
+ try {
+ if(action!=null)
+ {
+ if(action.getActionType() == ActionType.NORMAL)
+ {
+ Dragboard db = startDragAndDrop(TransferMode.ANY);
+
+ ClipboardContent content = new ClipboardContent();
+
+ Action newAction = (Action) action.clone();
+
+ newAction.setIDRandom();
+ newAction.setParent(getStreamPiParent());
+
+ content.put(Action.getDataFormat(), newAction);
+
+ db.setContent(content);
+
+ mouseEvent.consume();
+ }
+ }
+ }
+ catch (CloneNotSupportedException e)
+ {
+ e.printStackTrace();
+ }
+ });
+
+ setOnMouseClicked(mouseEvent -> {
+ if(action != null && mouseEvent.getButton().equals(MouseButton.PRIMARY))
+ {
+ if(mouseEvent.getClickCount() == 2 && action.getActionType() == ActionType.FOLDER)
+ {
+ getActionDetailsPaneListener().onOpenFolderButtonClicked();
+ }
+ else
+ {
+ try
+ {
+ actionDetailsPaneListener.onActionClicked(action, this);
+ }
+ catch (MinorException e)
+ {
+ exceptionAndAlertHandler.handleMinorException(e);
+ e.printStackTrace();
+ }
+ }
+ }
+ });
+
+ setCache(true);
+ setCacheHint(CacheHint.SPEED);
+ }
+
+ public void setInvalid(boolean invalid)
+ {
+ if(invalid)
+ {
+ getStyleClass().remove("action_box_valid");
+ getStyleClass().add("action_box_invalid");
+ }
+ else
+ {
+ getStyleClass().remove("action_box_invalid");
+ getStyleClass().add("action_box_valid");
+ }
+
+ }
+
+ public ActionDetailsPaneListener getActionDetailsPaneListener() {
+ return actionDetailsPaneListener;
+ }
+
+
+ public ActionGridPaneListener getActionGridPaneListener() {
+ return actionGridPaneListener;
+ }
+
+ private int size;
+ private ActionGridPaneListener actionGridPaneListener;
+ public ActionBox(int size, ActionDetailsPaneListener actionDetailsPaneListener, ActionGridPaneListener actionGridPaneListener)
+ {
+ this.actionGridPaneListener = actionGridPaneListener;
+ this.actionDetailsPaneListener = actionDetailsPaneListener;
+ this.size = size;
+ baseInit();
+ }
+
+ public static Action deserialize(ByteBuffer buffer) {
+ try {
+ ByteArrayInputStream is = new ByteArrayInputStream(buffer.array());
+ ObjectInputStream ois = new ObjectInputStream(is);
+ Action obj = (Action) ois.readObject();
+ return obj;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void setIcon(byte[] iconByteArray)
+ {
+ if(iconByteArray == null)
+ {
+ getStyleClass().remove("action_box_icon_present");
+ getStyleClass().add("action_box_icon_not_present");
+ setBackground(null);
+ return;
+ }
+ else
+ {
+ getStyleClass().add("action_box_icon_present");
+ getStyleClass().remove("action_box_icon_not_present");
+
+
+ setBackground(
+ new Background(
+ new BackgroundImage(new Image(
+ new ByteArrayInputStream(iconByteArray), size, size, false, true
+ ), BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.CENTER,
+
+ new BackgroundSize(100, 100, true, true, true, false))
+ )
+ );
+ }
+ }
+
+ private Action action;
+ private ExceptionAndAlertHandler exceptionAndAlertHandler;
+
+ private String parent;
+
+ public String getStreamPiParent() {
+ return parent;
+ }
+
+ public void setStreamPiParent(String parent) {
+ this.parent = parent;
+ }
+
+ public ActionBox(int size, Action action, ActionDetailsPaneListener actionDetailsPaneListener, ExceptionAndAlertHandler exceptionAndAlertHandler, ActionGridPaneListener actionGridPaneListener)
+ {
+ this.actionGridPaneListener = actionGridPaneListener;
+ this.exceptionAndAlertHandler = exceptionAndAlertHandler;
+ this.action = action;
+ this.actionDetailsPaneListener = actionDetailsPaneListener;
+ this.size = size;
+
+
+
+ baseInit();
+
+ init();
+
+ }
+
+ public void setAction(Action action)
+ {
+ this.action = action;
+ }
+
+ public void init()
+ {
+ if(action.isShowDisplayText())
+ setDisplayTextLabel(action.getDisplayText());
+ else
+ setDisplayTextLabel("");
+
+ setDisplayTextAlignment(action.getDisplayTextAlignment());
+ setBackgroundColour(action.getBgColourHex());
+ setDisplayTextFontColour(action.getDisplayTextFontColourHex());
+
+ setInvalid(action.isInvalid());
+
+ Platform.runLater(()->{
+ if(action.isHasIcon() && action.isShowIcon())
+ {
+ setIcon(action.getIconAsByteArray());
+ }
+ else
+ {
+ setIcon(null);
+ }
+ });
+ }
+
+ public void setDisplayTextLabel(String text)
+ {
+ displayTextLabel.setText(text);
+ }
+
+ public void setDisplayTextAlignment(DisplayTextAlignment displayTextAlignment)
+ {
+ if(displayTextAlignment == DisplayTextAlignment.CENTER)
+ displayTextLabel.setAlignment(Pos.CENTER);
+ else if (displayTextAlignment == DisplayTextAlignment.BOTTOM)
+ displayTextLabel.setAlignment(Pos.BOTTOM_CENTER);
+ else if (displayTextAlignment == DisplayTextAlignment.TOP)
+ displayTextLabel.setAlignment(Pos.TOP_CENTER);
+ }
+
+ public void setDisplayTextFontColour(String colour)
+ {
+ System.out.println("COLOr : "+colour);
+ if(!colour.isEmpty())
+ displayTextLabel.setStyle("-fx-text-fill : "+colour+";");
+ }
+
+ public void setBackgroundColour(String colour)
+ {
+ System.out.println("COLOr : "+colour);
+ if(!colour.isEmpty() && action.getIconAsByteArray() == null)
+ setStyle("-fx-background-color : "+colour);
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/dashboard/actiongridpane/ActionGridPane.java
@@ -0,0 +1,295 @@
+package com.stream_pi.server.window.dashboard.actiongridpane;
+
+import com.stream_pi.actionapi.action.Action;
+import com.stream_pi.actionapi.action.Location;
+import com.stream_pi.actionapi.otheractions.FolderAction;
+import com.stream_pi.server.client.Client;
+import com.stream_pi.server.client.ClientProfile;
+import com.stream_pi.server.io.Config;
+import com.stream_pi.server.window.ExceptionAndAlertHandler;
+import com.stream_pi.server.window.dashboard.actiondetailpane.ActionDetailsPaneListener;
+import com.stream_pi.util.exception.MinorException;
+import com.stream_pi.util.exception.SevereException;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.Node;
+import javafx.scene.control.ScrollPane;
+import javafx.scene.layout.*;
+import org.kordamp.ikonli.javafx.FontIcon;
+
+import java.util.logging.Logger;
+
+public class ActionGridPane extends ScrollPane implements ActionGridPaneListener {
+
+ private ExceptionAndAlertHandler exceptionAndAlertHandler;
+ private ActionDetailsPaneListener actionDetailsPaneListener;
+
+ public ActionGridPane(ExceptionAndAlertHandler exceptionAndAlertHandler)
+ {
+ logger = Logger.getLogger(ActionGridPane.class.getName());
+ this.exceptionAndAlertHandler = exceptionAndAlertHandler;
+ getStyleClass().add("action_grid_pane_scroll_pane");
+
+ VBox.setVgrow(this, Priority.ALWAYS);
+
+ actionsGridPane = new GridPane();
+ actionsGridPane.setPadding(new Insets(5.0));
+ actionsGridPane.getStyleClass().add("action_grid_pane");
+
+ actionsGridPane.setPrefSize(USE_COMPUTED_SIZE, USE_COMPUTED_SIZE);
+
+ setContent(actionsGridPane);
+ }
+
+ public void setActionDetailsPaneListener(ActionDetailsPaneListener actionDetailsPaneListener) {
+ this.actionDetailsPaneListener = actionDetailsPaneListener;
+ }
+
+ private String currentParent;
+
+ public void setCurrentParent(String currentParent) {
+ this.currentParent = currentParent;
+ }
+
+ public ClientProfile getClientProfile() {
+ return clientProfile;
+ }
+
+ private Client client;
+
+ public void setClient(Client client) {
+ this.client = client;
+ }
+
+ public Client getClient() {
+ return client;
+ }
+
+ private int rows, cols;
+
+ private GridPane actionsGridPane;
+
+ private ClientProfile clientProfile;
+
+ public void setClientProfile(ClientProfile clientProfile)
+ {
+ this.clientProfile = clientProfile;
+
+ setCurrentParent("root");
+ setRows(clientProfile.getRows());
+ setCols(clientProfile.getCols());
+ }
+
+
+ public String getCurrentParent() {
+ return currentParent;
+ }
+
+ public StackPane getFolderBackButton() throws SevereException
+ {
+ StackPane stackPane = new StackPane();
+ stackPane.getStyleClass().add("action_box");
+ stackPane.getStyleClass().add("action_box_valid");
+
+ stackPane.setPrefSize(
+ Config.getInstance().getActionGridActionSize(),
+ Config.getInstance().getActionGridActionSize()
+ );
+
+ FontIcon fontIcon = new FontIcon("fas-chevron-left");
+
+ fontIcon.setIconSize(Config.getInstance().getActionGridActionSize() - 30);
+
+ stackPane.setAlignment(Pos.CENTER);
+ stackPane.getChildren().add(fontIcon);
+
+ stackPane.setOnMouseClicked(e->returnToPreviousParent());
+
+ return stackPane;
+ }
+
+ public void renderGrid() throws SevereException {
+ clear();
+
+ actionsGridPane.setHgap(Config.getInstance().getActionGridActionGap());
+ actionsGridPane.setVgap(Config.getInstance().getActionGridActionGap());
+
+ boolean isFolder = false;
+
+ if(!getCurrentParent().equals("root"))
+ {
+ isFolder = true;
+
+ actionsGridPane.add(getFolderBackButton(), 0,0);
+ }
+
+ for(int row = 0; row<rows; row++)
+ {
+ for(int col = 0; col<cols; col++)
+ {
+ if(row == 0 && col == 0 && isFolder)
+ continue;
+
+ ActionBox actionBox = new ActionBox(Config.getInstance().getActionGridActionSize(), actionDetailsPaneListener, this);
+
+ actionBox.setStreamPiParent(currentParent);
+ actionBox.setRow(row);
+ actionBox.setCol(col);
+
+ actionsGridPane.add(actionBox, row, col);
+
+ }
+ }
+ }
+
+ public void renderActions()
+ {
+ StringBuilder errors = new StringBuilder();
+ for(String action1x : getClientProfile().getActionsKeySet())
+ {
+ Action eachAction = getClientProfile().getActionByID(action1x);
+ logger.info("action ID : "+eachAction.getID()+
+ "\nInvalid : "+eachAction.isInvalid());
+
+ try {
+ renderAction(eachAction);
+ }
+ catch (SevereException e)
+ {
+ exceptionAndAlertHandler.handleSevereException(e);
+ }
+ catch (MinorException e)
+ {
+ errors.append("*").append(e.getShortMessage()).append("\n");
+ }
+ }
+
+ if(!errors.toString().isEmpty())
+ {
+ exceptionAndAlertHandler.handleMinorException(new MinorException("Error while rendering following actions", errors.toString()));
+ }
+ }
+
+ public void clear()
+ {
+ actionsGridPane.getChildren().clear();
+ }
+
+ private Logger logger;
+
+ public void renderAction(Action action) throws SevereException, MinorException
+ {
+ if(!action.getParent().equals(currentParent))
+ {
+ logger.info("Skipping action "+action.getID()+", not current parent!");
+ return;
+ }
+
+ if(action.getLocation().getRow()==-1)
+ {
+ logger.info("action has -1 rowIndex. Probably Combine action. Skipping ...");
+ return;
+ }
+
+ if(action.getLocation().getRow() >= rows || action.getLocation().getCol() >= cols)
+ {
+ throw new MinorException("action "+action.getDisplayText()+" ("+action.getID()+") falls outside bounds.\n" +
+ " Consider increasing rows/cols from client settings and relocating/deleting it.");
+ }
+
+
+ ActionBox actionBox = new ActionBox(Config.getInstance().getActionGridActionSize(), action, actionDetailsPaneListener, exceptionAndAlertHandler, this);
+
+ Location location = action.getLocation();
+
+ actionBox.setStreamPiParent(currentParent);
+ actionBox.setRow(location.getRow());
+ actionBox.setCol(location.getCol());
+
+ for(Node node : actionsGridPane.getChildren())
+ {
+ if(GridPane.getColumnIndex(node) == location.getRow() &&
+ GridPane.getRowIndex(node) == location.getCol())
+ {
+ actionsGridPane.getChildren().remove(node);
+ break;
+ }
+ }
+
+ System.out.println(location.getCol()+","+location.getRow());
+ actionsGridPane.add(actionBox, location.getRow(), location.getCol());
+
+ }
+
+ public void setRows(int rows)
+ {
+ this.rows = rows;
+ }
+
+ public void setCols(int cols)
+ {
+ this.cols = cols;
+ }
+
+ public int getRows()
+ {
+ return rows;
+ }
+
+ public int getCols()
+ {
+ return cols;
+ }
+
+
+ @Override
+ public void addActionToCurrentClientProfile(Action newAction) {
+ try {
+ getClientProfile().addAction(newAction);
+ } catch (CloneNotSupportedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private String previousParent;
+
+ public void setPreviousParent(String previousParent) {
+ this.previousParent = previousParent;
+ }
+
+ public String getPreviousParent() {
+ return previousParent;
+ }
+
+ @Override
+ public void renderFolder(FolderAction action) {
+ setCurrentParent(action.getID());
+ setPreviousParent(action.getParent());
+ try {
+ renderGrid();
+ renderActions();
+ } catch (SevereException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void returnToPreviousParent()
+ {
+ setCurrentParent(getPreviousParent());
+
+ if(!getPreviousParent().equals("root"))
+ {
+ System.out.println("parent : "+getPreviousParent());
+ setPreviousParent(getClientProfile().getActionByID(
+ getPreviousParent()
+ ).getParent());
+ }
+
+ try {
+ renderGrid();
+ renderActions();
+ } catch (SevereException e) {
+ e.printStackTrace();
+ }
+ }
+}
A
src/main/java/com/stream_pi/server/window/dashboard/actiongridpane/ActionGridPaneListener.java
+10
−0
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/dashboard/actiongridpane/ActionGridPaneListener.java
@@ -0,0 +1,10 @@
+package com.stream_pi.server.window.dashboard.actiongridpane;
+
+import com.stream_pi.actionapi.action.Action;
+import com.stream_pi.actionapi.otheractions.FolderAction;
+
+public interface ActionGridPaneListener {
+ void addActionToCurrentClientProfile(Action newAction);
+
+ void renderFolder(FolderAction action);
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/firsttimeuse/FinalConfigPane.java
@@ -0,0 +1,108 @@
+package com.stream_pi.server.window.firsttimeuse;
+
+import com.stream_pi.server.connection.ServerListener;
+import com.stream_pi.server.io.Config;
+import com.stream_pi.server.window.ExceptionAndAlertHandler;
+import com.stream_pi.util.exception.SevereException;
+import com.stream_pi.util.uihelper.HBoxInputBox;
+import com.stream_pi.util.uihelper.SpaceFiller;
+import com.stream_pi.util.uihelper.SpaceFiller.FillerType;
+
+import javafx.geometry.Pos;
+import javafx.scene.control.Alert;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextField;
+import javafx.scene.control.Alert.AlertType;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
+import javafx.stage.Stage;
+
+public class FinalConfigPane extends VBox
+{
+ private TextField serverNicknameTextField;
+ private TextField serverPortTextField;
+
+ private ExceptionAndAlertHandler exceptionAndAlertHandler;
+ private ServerListener serverListener;
+
+ public FinalConfigPane(ExceptionAndAlertHandler exceptionAndAlertHandler, ServerListener serverListener)
+ {
+ this.exceptionAndAlertHandler = exceptionAndAlertHandler;
+ this.serverListener = serverListener;
+
+ getStyleClass().add("first_time_use_pane_final_config");
+
+ Label label = new Label("Thats it. Now just name your Stream-Pi Server, and the port where the server will run on!\n" +
+ "You can leave the default value of the port as it is.");
+ label.setWrapText(true);
+ label.getStyleClass().add("first_time_use_pane_final_config_label");
+
+ serverNicknameTextField = new TextField();
+ serverPortTextField = new TextField("2004");
+
+ HBoxInputBox serverNickNameInputBox = new HBoxInputBox("Server Nickname", serverNicknameTextField, 200);
+ HBoxInputBox serverPortInputBox = new HBoxInputBox("Server Port", serverPortTextField);
+
+ Button confirmButton = new Button("Confirm");
+ confirmButton.setOnAction(event -> onConfirmButtonClicked());
+ HBox bBar = new HBox(confirmButton);
+ bBar.setAlignment(Pos.CENTER_RIGHT);
+
+ getChildren().addAll(label, serverNickNameInputBox, serverPortInputBox, new SpaceFiller(FillerType.VBox), bBar);
+
+ setSpacing(10.0);
+
+ setVisible(false);
+ }
+
+ private void onConfirmButtonClicked()
+ {
+ StringBuilder errors = new StringBuilder();
+
+ String serverNameStr = serverNicknameTextField.getText();
+ String serverPortStr = serverPortTextField.getText();
+
+ if(serverNameStr.isBlank() || serverNameStr.isEmpty())
+ {
+ errors.append("* Server Name cannot be blank.\n");
+ }
+
+ int serverPort=-1;
+ try {
+ serverPort = Integer.parseInt(serverPortStr);
+
+ if (serverPort < 1024)
+ errors.append("* Server Port must be more than 1024");
+ }
+ catch (NumberFormatException e)
+ {
+ errors.append("* Server Port must be integer.\n");
+ }
+
+ if(errors.toString().isEmpty())
+ {
+ try
+ {
+ Config.getInstance().setServerName(serverNameStr);
+ Config.getInstance().setServerPort(serverPort);
+ Config.getInstance().setFirstTimeUse(false);
+ Config.getInstance().save();
+
+ serverListener.othInit();
+
+ ((Stage) getScene().getWindow()).close();
+ }
+ catch(SevereException e)
+ {
+ exceptionAndAlertHandler.handleSevereException(e);
+ }
+ }
+ else
+ {
+ Alert alert = new Alert(AlertType.ERROR);
+ alert.setContentText("Please rectify the following errors and try again:\n"+errors.toString());
+ alert.show();
+ }
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/firsttimeuse/FirstTimeUse.java
@@ -0,0 +1,143 @@
+package com.stream_pi.server.window.firsttimeuse;
+
+import com.stream_pi.server.Main;
+import com.stream_pi.server.connection.ServerListener;
+import com.stream_pi.server.window.ExceptionAndAlertHandler;
+import com.stream_pi.util.uihelper.SpaceFiller;
+import com.stream_pi.util.uihelper.SpaceFiller.FillerType;
+
+import javafx.geometry.Insets;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.StackPane;
+import javafx.scene.layout.VBox;
+import javafx.scene.text.Font;
+
+public class FirstTimeUse extends VBox{
+
+
+ public FirstTimeUse(ExceptionAndAlertHandler exceptionAndAlertHandler, ServerListener serverListener)
+ {
+ Font.loadFont(Main.class.getResourceAsStream("Roboto.ttf"), 13);
+ getStylesheets().add(Main.class.getResource("style.css").toExternalForm());
+
+ getStyleClass().add("first_time_use_pane");
+
+ setSpacing(10.0);
+ setPadding(new Insets(5));
+
+ headingLabel = new Label();
+ headingLabel.getStyleClass().add("first_time_use_pane_heading_label");
+
+ StackPane stackPane = new StackPane();
+ stackPane.getStyleClass().add("first_time_use_pane_stackpane");
+
+ VBox.setVgrow(stackPane, Priority.ALWAYS);
+
+ welcomePane = new WelcomePane();
+ licensePane = new LicensePane();
+ finalConfigPane = new FinalConfigPane(exceptionAndAlertHandler, serverListener);
+
+ stackPane.getChildren().addAll(
+ welcomePane,
+ licensePane,
+ finalConfigPane
+ );
+
+
+ nextButton = new Button("Next");
+ nextButton.setOnAction(event-> onNextButtonClicked());
+
+ previousButton = new Button("Previous");
+ previousButton.setOnAction(event-> onPreviousButtonClicked());
+
+
+ HBox buttonBar = new HBox(previousButton, new SpaceFiller(FillerType.HBox), nextButton);
+ buttonBar.setSpacing(10.0);
+
+ getChildren().addAll(headingLabel, stackPane, buttonBar);
+
+ setWindow(WindowName.WELCOME);
+ }
+
+ private Label headingLabel;
+ private Button nextButton;
+ private Button previousButton;
+ private WelcomePane welcomePane;
+ private LicensePane licensePane;
+ private FinalConfigPane finalConfigPane;
+
+ private WindowName windowName;
+
+ private void onNextButtonClicked()
+ {
+ if(windowName == WindowName.WELCOME)
+ {
+ setWindow(WindowName.LICENSE);
+ }
+ else if(windowName == WindowName.LICENSE)
+ {
+ setWindow(WindowName.FINAL);
+ }
+ }
+
+ private void onPreviousButtonClicked()
+ {
+ if(windowName == WindowName.FINAL)
+ {
+ setWindow(WindowName.LICENSE);
+ }
+ else if(windowName == WindowName.LICENSE)
+ {
+ setWindow(WindowName.WELCOME);
+ }
+ }
+
+ private void setWindow(WindowName windowName)
+ {
+ if (windowName == WindowName.WELCOME)
+ {
+ this.windowName = WindowName.WELCOME;
+ welcomePane.toFront();
+ welcomePane.setVisible(true);
+ licensePane.setVisible(false);
+ finalConfigPane.setVisible(false);
+
+ headingLabel.setText("");
+
+ nextButton.setDisable(false);
+ previousButton.setDisable(true);
+ }
+ else if (windowName == WindowName.LICENSE)
+ {
+ this.windowName = WindowName.LICENSE;
+ licensePane.toFront();
+ welcomePane.setVisible(false);
+ licensePane.setVisible(true);
+ finalConfigPane.setVisible(false);
+
+ headingLabel.setText("License Agreement");
+
+ nextButton.setDisable(false);
+ previousButton.setDisable(false);
+ }
+ else if (windowName == WindowName.FINAL)
+ {
+ this.windowName = WindowName.FINAL;
+ finalConfigPane.toFront();
+ welcomePane.setVisible(false);
+ licensePane.setVisible(false);
+ finalConfigPane.setVisible(true);
+
+ headingLabel.setText("Finishing up ...");
+
+ nextButton.setDisable(true);
+ previousButton.setDisable(false);
+ }
+ }
+
+
+
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/firsttimeuse/LicensePane.java
@@ -0,0 +1,28 @@
+package com.stream_pi.server.window.firsttimeuse;
+
+import com.stream_pi.server.info.License;
+
+import javafx.scene.control.Label;
+import javafx.scene.control.TextArea;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.VBox;
+
+public class LicensePane extends VBox {
+ public LicensePane()
+ {
+ getStyleClass().add("first_time_use_pane_license");
+
+ Label label = new Label("By Clicking on 'Next', you agree with the license of StreamPi, and the license(s) of the library(s) used/included with this software.");
+ label.prefWidthProperty().bind(widthProperty());
+ label.setWrapText(true);
+
+ TextArea licenseTextArea = new TextArea(License.getLicense());
+ licenseTextArea.setWrapText(false);
+ licenseTextArea.setEditable(false);
+
+ licenseTextArea.prefWidthProperty().bind(widthProperty());
+ VBox.setVgrow(licenseTextArea, Priority.ALWAYS);
+
+ getChildren().addAll(label, licenseTextArea);
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/firsttimeuse/WelcomePane.java
@@ -0,0 +1,25 @@
+package com.stream_pi.server.window.firsttimeuse;
+
+import javafx.geometry.Pos;
+import javafx.scene.control.Label;
+import javafx.scene.layout.VBox;
+
+public class WelcomePane extends VBox{
+ public WelcomePane()
+ {
+ getStyleClass().add("first_time_use_pane_welcome");
+
+ Label welcomeLabel = new Label("Welcome!");
+ welcomeLabel.getStyleClass().add("first_time_use_welcome_pane_welcome_label");
+
+ Label nextToContinue = new Label("Click on Next to continue with the setup.");
+ nextToContinue.getStyleClass().add("first_time_use_welcome_pane_next_to_continue_label");
+
+
+ setAlignment(Pos.CENTER);
+ setSpacing(5.0);
+ getChildren().addAll(welcomeLabel, nextToContinue);
+
+ setVisible(false);
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/firsttimeuse/WindowName.java
@@ -0,0 +1,5 @@
+package com.stream_pi.server.window.firsttimeuse;
+
+public enum WindowName {
+ WELCOME, LICENSE, FINAL
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/settings/About.java
@@ -0,0 +1,104 @@
+package com.stream_pi.server.window.settings;
+
+import com.stream_pi.actionapi.ActionAPI;
+import com.stream_pi.server.info.License;
+import com.stream_pi.server.info.ServerInfo;
+import com.stream_pi.server.Main;
+import javafx.application.HostServices;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.control.Hyperlink;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextArea;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.VBox;
+
+public class About extends VBox{
+
+ private HostServices hostServices;
+
+ public About(HostServices hostServices)
+ {
+ getStyleClass().add("about");
+ this.hostServices = hostServices;
+
+ setAlignment(Pos.TOP_CENTER);
+
+ Image appIcon = new Image(Main.class.getResourceAsStream("app_icon.png"));
+ ImageView appIconImageView = new ImageView(appIcon);
+ appIconImageView.setFitHeight(196);
+ appIconImageView.setFitWidth(182);
+
+ Label licenseLabel = new Label("License");
+ licenseLabel.getStyleClass().add("settings_about_license_label");
+
+ VBox.setMargin(licenseLabel, new Insets(20, 0 , 10 ,0));
+
+ TextArea licenseTextArea = new TextArea(License.getLicense());
+ licenseTextArea.setWrapText(false);
+ licenseTextArea.setEditable(false);
+ licenseTextArea.setMaxWidth(550);
+
+ VBox.setVgrow(licenseTextArea, Priority.ALWAYS);
+
+ HBox links = new HBox();
+
+ Hyperlink github = new Hyperlink("GitHub");
+ github.setOnAction(event -> {
+ openWebpage("https://github.com/Stream-Pi");
+ });
+
+ Hyperlink discord = new Hyperlink("Discord");
+ discord.setOnAction(event -> {
+ openWebpage("https://discord.gg/BExqGmk");
+ });
+
+ Hyperlink website = new Hyperlink("Website");
+ website.setOnAction(event -> {
+ openWebpage("https://stream-pi.com");
+ });
+
+ Hyperlink twitter = new Hyperlink("Twitter");
+ twitter.setOnAction(event -> {
+ openWebpage("https://twitter.com/Stream_Pi");
+ });
+
+ Hyperlink matrix = new Hyperlink("Matrix");
+ matrix.setOnAction(event -> {
+ openWebpage("https://matrix.to/#/#stream-pi_general:matrix.org");
+ });
+
+
+ links.setSpacing(30);
+ links.setAlignment(Pos.CENTER);
+ links.getChildren().addAll(github, matrix, discord, website, twitter);
+
+ Hyperlink donateButton = new Hyperlink("DONATE");
+ donateButton.setOnAction(event -> {
+ openWebpage("https://www.patreon.com/streampi");
+ });
+ donateButton.getStyleClass().add("settings_about_donate_hyperlink");
+
+
+ ServerInfo serverInfo = ServerInfo.getInstance();
+
+ Label versionText = new Label(serverInfo.getVersion().getText() + " - "+ serverInfo.getPlatformType().getUIName() + " - "+ serverInfo.getReleaseStatus().getUIName());
+ Label commStandardLabel = new Label("Comm Standard "+serverInfo.getCommStandardVersion().getText());
+ Label minThemeAPILabel = new Label("Min ThemeAPI "+serverInfo.getMinThemeSupportVersion().getText());
+ Label minActionAPILabel = new Label("Min ActionAPI "+serverInfo.getMinPluginSupportVersion().getText());
+
+
+ Label currentActionAPILabel = new Label("ActionAPI "+ ActionAPI.API_VERSION.getText());
+
+ setSpacing(3);
+
+ getChildren().addAll(appIconImageView, licenseLabel, licenseTextArea, links, donateButton, versionText, commStandardLabel, minThemeAPILabel, minActionAPILabel, currentActionAPILabel);
+ }
+
+ public void openWebpage(String url) {
+ hostServices.showDocument(url);
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/settings/ClientsSettings.java
@@ -0,0 +1,710 @@
+package com.stream_pi.server.window.settings;
+
+import com.stream_pi.server.client.Client;
+import com.stream_pi.server.client.ClientProfile;
+import com.stream_pi.server.client.ClientTheme;
+import com.stream_pi.server.connection.ClientConnection;
+import com.stream_pi.server.connection.ClientConnections;
+import com.stream_pi.server.connection.ServerListener;
+import com.stream_pi.server.window.ExceptionAndAlertHandler;
+import com.stream_pi.util.exception.MinorException;
+import com.stream_pi.util.exception.SevereException;
+import com.stream_pi.util.uihelper.HBoxInputBox;
+import com.stream_pi.util.uihelper.SpaceFiller;
+import com.stream_pi.util.platform.ReleaseStatus;
+import javafx.application.Platform;
+import javafx.collections.FXCollections;
+import javafx.concurrent.Task;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.CacheHint;
+import javafx.scene.control.*;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.VBox;
+import javafx.util.Callback;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+public class ClientsSettings extends VBox {
+ private VBox clientsSettingsVBox;
+ private Button saveButton;
+
+ private ServerListener serverListener;
+
+ private Logger logger;
+
+ private ExceptionAndAlertHandler exceptionAndAlertHandler;
+
+ public ClientsSettings(ExceptionAndAlertHandler exceptionAndAlertHandler, ServerListener serverListener)
+ {
+ getStyleClass().add("clients_settings");
+ this.serverListener = serverListener;
+ this.exceptionAndAlertHandler = exceptionAndAlertHandler;
+
+ clientSettingsVBoxArrayList = new ArrayList<>();
+
+ setPadding(new Insets(10.0));
+
+ logger = Logger.getLogger(ClientsSettings.class.getName());
+
+ clientsSettingsVBox = new VBox();
+ clientsSettingsVBox.setSpacing(20.0);
+ clientsSettingsVBox.setAlignment(Pos.TOP_CENTER);
+
+ setAlignment(Pos.TOP_CENTER);
+
+ ScrollPane scrollPane = new ScrollPane();
+ scrollPane.getStyleClass().add("clients_settings_scroll_pane");
+ scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
+ VBox.setVgrow(scrollPane, Priority.ALWAYS);
+ scrollPane.maxWidthProperty().bind(widthProperty().multiply(0.8));
+
+ clientsSettingsVBox.prefWidthProperty().bind(scrollPane.widthProperty().subtract(25));
+ scrollPane.setContent(clientsSettingsVBox);
+
+ saveButton = new Button("Save");
+ saveButton.setOnAction(event -> onSaveButtonClicked());
+
+ HBox hBox = new HBox(saveButton);
+ hBox.setAlignment(Pos.CENTER_RIGHT);
+
+ getChildren().addAll(scrollPane, hBox);
+
+ setCache(true);
+ setCacheHint(CacheHint.SPEED);
+ }
+
+ public void onSaveButtonClicked()
+ {
+ new Thread(new Task<Void>() {
+ @Override
+ protected Void call()
+ {
+ try
+ {
+ Platform.runLater(()->saveButton.setDisable(true));
+ StringBuilder finalErrors = new StringBuilder();
+
+ for(ClientSettingsVBox clientSettingsVBox : clientSettingsVBoxArrayList)
+ {
+ StringBuilder errors = new StringBuilder();
+
+ if(clientSettingsVBox.getNickname().isBlank())
+ errors.append(" Cannot have blank nickname. \n");
+
+ try {
+ Double.parseDouble(clientSettingsVBox.getStartupWindowHeight());
+ }
+ catch (NumberFormatException e)
+ {
+ errors.append(" Must have integer display height. \n");
+ }
+
+ try {
+ Double.parseDouble(clientSettingsVBox.getStartupWindowWidth());
+ }
+ catch (NumberFormatException e)
+ {
+ errors.append(" Must have integer display width. \n");
+ }
+
+ for(ClientProfileVBox clientProfileVBox : clientSettingsVBox.getClientProfileVBoxes())
+ {
+ StringBuilder errors2 = new StringBuilder();
+
+ if(clientProfileVBox.getName().isBlank())
+ errors2.append(" cannot have blank nickname. \n");
+
+ try {
+ Integer.parseInt(clientProfileVBox.getActionSize());
+ }
+ catch (NumberFormatException e)
+ {
+ errors2.append(" Must have integer action Size. \n");
+ }
+
+
+ try {
+ Integer.parseInt(clientProfileVBox.getActionGap());
+ }
+ catch (NumberFormatException e)
+ {
+ errors2.append(" Must have integer action Gap. \n");
+ }
+
+
+ try {
+ int rows = Integer.parseInt(clientProfileVBox.getRows());
+
+ int actionsSize = Integer.parseInt(clientProfileVBox.getActionSize());
+ double startupWidth = Double.parseDouble(clientSettingsVBox.getStartupWindowWidth());
+
+
+ if((rows*actionsSize) > (startupWidth - 25) && clientSettingsVBox.getPlatform()!= com.stream_pi.util.platform.Platform.ANDROID)
+ {
+ errors2.append(" Rows out of bounds of screen size. \n"+startupWidth);
+ }
+ }
+ catch (NumberFormatException e)
+ {
+ errors2.append(" Must have integer Rows. \n");
+ }
+
+
+ try {
+ int cols = Integer.parseInt(clientProfileVBox.getCols());
+
+ int actionsSize = Integer.parseInt(clientProfileVBox.getActionSize());
+ double startupHeight = Double.parseDouble(clientSettingsVBox.getStartupWindowHeight());
+
+ if((cols*actionsSize) > (startupHeight - 25) && clientSettingsVBox.getPlatform()!= com.stream_pi.util.platform.Platform.ANDROID)
+ {
+ errors2.append(" Cols out of bounds of screen size. \n"+startupHeight);
+ }
+ }
+ catch (NumberFormatException e)
+ {
+ errors2.append(" Must have integer Columns. \n");
+ }
+
+
+ if(!errors2.toString().isEmpty())
+ {
+ errors.append(" ")
+ .append(clientProfileVBox.getRealName())
+ .append("\n")
+ .append(errors2.toString())
+ .append("\n");
+ }
+ }
+
+
+ if(!errors.toString().isEmpty())
+ {
+ finalErrors.append("* ")
+ .append(clientSettingsVBox.getRealNickName())
+ .append("\n")
+ .append(errors.toString())
+ .append("\n");
+ }
+
+
+
+ }
+
+ if(!finalErrors.toString().isEmpty())
+ throw new MinorException("You made form mistakes",
+ "Please fix the following issues : \n"+finalErrors.toString());
+
+
+
+ //save details and values
+ for(ClientSettingsVBox clientSettingsVBox : clientSettingsVBoxArrayList)
+ {
+ clientSettingsVBox.saveClientAndProfileDetails();
+ }
+
+ loadData();
+ serverListener.clearTemp();
+ }
+ catch (MinorException e)
+ {
+ e.printStackTrace();
+ exceptionAndAlertHandler.handleMinorException(e);
+ }
+ catch (SevereException e)
+ {
+ e.printStackTrace();
+ exceptionAndAlertHandler.handleSevereException(e);
+ }
+ catch (CloneNotSupportedException e)
+ {
+ e.printStackTrace();
+ exceptionAndAlertHandler.handleSevereException(new SevereException(
+ e.getMessage()
+ ));
+ }
+ finally
+ {
+ Platform.runLater(()->saveButton.setDisable(false));
+ }
+ return null;
+ }
+ }).start();
+ }
+
+ private ArrayList<ClientSettingsVBox> clientSettingsVBoxArrayList;
+
+ public void loadData()
+ {
+ logger.info("Loading client data into ClientsSettings ...");
+
+ Platform.runLater(()-> clientsSettingsVBox.getChildren().clear());
+ clientSettingsVBoxArrayList.clear();
+
+ List<ClientConnection> clientConnections = ClientConnections.getInstance().getConnections();
+
+ if(clientConnections.size() == 0)
+ {
+ Platform.runLater(()->{
+ clientsSettingsVBox.getChildren().add(new Label("No Clients Connected."));
+ saveButton.setVisible(false);
+ });
+ }
+ else
+ {
+ Platform.runLater(()->saveButton.setVisible(true));
+ for (ClientConnection clientConnection : clientConnections) {
+ ClientSettingsVBox clientSettingsVBox = new ClientSettingsVBox(clientConnection);
+
+ clientSettingsVBoxArrayList.add(clientSettingsVBox);
+ Platform.runLater(()->clientsSettingsVBox.getChildren().add(clientSettingsVBox));
+ }
+ }
+
+ logger.info("... Done!");
+ }
+
+ public class ClientSettingsVBox extends VBox
+ {
+ private ComboBox<ClientProfile> profilesComboBox;
+
+ private ComboBox<ClientTheme> themesComboBox;
+
+ private TextField startupWindowHeightTextField;
+
+ public String getStartupWindowHeight() {
+ return startupWindowHeightTextField.getText();
+ }
+
+ private TextField startupWindowWidthTextField;
+
+ public String getStartupWindowWidth() {
+ return startupWindowWidthTextField.getText();
+ }
+
+ private TextField nicknameTextField;
+
+ public String getNickname() {
+ return nicknameTextField.getText();
+ }
+
+ private Label nickNameLabel;
+
+ private Label versionLabel;
+
+ public String getRealNickName()
+ {
+ return nickNameLabel.getText();
+ }
+
+ private com.stream_pi.util.platform.Platform platform;
+
+ public com.stream_pi.util.platform.Platform getPlatform() {
+ return platform;
+ }
+
+ private Label socketConnectionLabel;
+
+ private ClientConnection connection;
+
+ private Accordion profilesAccordion;
+
+ private ArrayList<ClientProfileVBox> clientProfileVBoxes;
+
+ private Label platformLabel;
+
+ private HBoxInputBox startupWindowHeightInputBox, startupWindowWidthInputBox;
+
+ public ArrayList<ClientProfileVBox> getClientProfileVBoxes() {
+ return clientProfileVBoxes;
+ }
+
+ public ClientSettingsVBox(ClientConnection connection)
+ {
+ this.connection = connection;
+ this.platform = connection.getClient().getPlatform();
+
+ clientProfileVBoxes = new ArrayList<>();
+
+ initUI();
+ loadValues();
+ }
+
+ public ClientConnection getConnection()
+ {
+ return connection;
+ }
+
+ public void saveClientAndProfileDetails() throws SevereException, CloneNotSupportedException, MinorException {
+ System.out.println("IIN");
+ getConnection().saveClientDetails(
+ nicknameTextField.getText(),
+ startupWindowWidthTextField.getText(),
+ startupWindowHeightTextField.getText(),
+ profilesComboBox.getSelectionModel().getSelectedItem().getID(),
+ themesComboBox.getSelectionModel().getSelectedItem().getThemeFullName()
+ );
+
+ System.out.println("OUT");
+
+ logger.info("Profiles : ");
+ for(ClientProfileVBox clientProfileVBox : clientProfileVBoxes)
+ {
+ logger.info("Name : "+clientProfileVBox.getClientProfile().getName());
+ getConnection().saveProfileDetails(clientProfileVBox.getClientProfile());
+ }
+
+
+ //remove deleted client profiles
+ for(ClientProfile clientProfile : connection.getClient().getAllClientProfiles())
+ {
+ boolean found = false;
+ for(ClientProfileVBox clientProfileVBox : clientProfileVBoxes)
+ {
+ if(clientProfileVBox.getClientProfile().getID().equals(clientProfile.getID()))
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if(!found)
+ {
+ connection.getClient().removeProfileFromID(clientProfile.getID());
+ connection.deleteProfile(clientProfile.getID());
+ }
+ }
+
+
+ }
+
+ public void initUI()
+ {
+ profilesComboBox = new ComboBox<>();
+ Callback<ListView<ClientProfile>, ListCell<ClientProfile>> profilesComboBoxFactory = new Callback<>() {
+ @Override
+ public ListCell<ClientProfile> call(ListView<ClientProfile> clientConnectionListView) {
+
+ return new ListCell<>() {
+ @Override
+ protected void updateItem(ClientProfile clientProfile, boolean b) {
+ super.updateItem(clientProfile, b);
+
+ if(clientProfile == null)
+ {
+ setText(null);
+ }
+ else
+ {
+ setText(clientProfile.getName());
+ }
+ }
+ };
+ }
+ };
+ profilesComboBox.setCellFactory(profilesComboBoxFactory);
+ profilesComboBox.setButtonCell(profilesComboBoxFactory.call(null));
+
+ themesComboBox = new ComboBox<>();
+ Callback<ListView<ClientTheme>, ListCell<ClientTheme>> themesComboBoxFactory = new Callback<>() {
+ @Override
+ public ListCell<ClientTheme> call(ListView<ClientTheme> clientConnectionListView) {
+
+ return new ListCell<>() {
+ @Override
+ protected void updateItem(ClientTheme clientTheme, boolean b) {
+ super.updateItem(clientTheme, b);
+
+ if(clientTheme == null)
+ {
+ setText(null);
+ }
+ else
+ {
+ setText(clientTheme.getShortName());
+ }
+ }
+ };
+ }
+ };
+ themesComboBox.setCellFactory(themesComboBoxFactory);
+ themesComboBox.setButtonCell(themesComboBoxFactory.call(null));
+
+ startupWindowHeightTextField = new TextField();
+ startupWindowWidthTextField = new TextField();
+
+ platformLabel = new Label();
+ platformLabel.getStyleClass().add("settings_client_platform_label");
+
+ socketConnectionLabel = new Label();
+ socketConnectionLabel.getStyleClass().add("settings_client_socket_connection_label");
+
+ nicknameTextField = new TextField();
+
+ nickNameLabel = new Label();
+ nickNameLabel.getStyleClass().add("settings_client_nick_name_label");
+
+ versionLabel = new Label();
+ versionLabel.getStyleClass().add("settings_client_version_label");
+
+ profilesAccordion = new Accordion();
+ VBox.setMargin(profilesAccordion, new Insets(0,0,20,0));
+
+
+ Button addNewProfileButton = new Button("Add new Profile");
+ addNewProfileButton.setOnAction(event -> onNewProfileButtonClicked());
+
+ setSpacing(10.0);
+
+ getStyleClass().add("settings_clients_each_client");
+
+
+ startupWindowHeightInputBox = new HBoxInputBox("Startup window Height", startupWindowHeightTextField);
+ startupWindowHeightInputBox.managedProperty().bind(startupWindowHeightInputBox.visibleProperty());
+
+ startupWindowWidthInputBox = new HBoxInputBox("Startup window Width", startupWindowWidthTextField);
+ startupWindowWidthInputBox.managedProperty().bind(startupWindowWidthInputBox.visibleProperty());
+
+
+ this.getChildren().addAll(
+ nickNameLabel,
+ socketConnectionLabel,
+ platformLabel,
+ versionLabel,
+ new HBoxInputBox("Nickname",nicknameTextField),
+ new HBox(
+ new Label("Theme"),
+ new SpaceFiller(SpaceFiller.FillerType.HBox),
+ themesComboBox
+ ),
+
+ startupWindowHeightInputBox,
+
+ startupWindowWidthInputBox,
+
+ new HBox(new Label("Startup Profile"),
+ new SpaceFiller(SpaceFiller.FillerType.HBox),
+ profilesComboBox),
+
+ addNewProfileButton,
+
+ profilesAccordion);
+ }
+
+ public void loadValues()
+ {
+ Client client = connection.getClient();
+
+ profilesComboBox.setItems(FXCollections.observableList(client.getAllClientProfiles()));
+ profilesComboBox.getSelectionModel().select(
+ client.getProfileByID(client.getDefaultProfileID())
+ );
+
+
+ themesComboBox.setItems(FXCollections.observableList(client.getThemes()));
+ themesComboBox.getSelectionModel().select(
+ client.getThemeByFullName(
+ client.getDefaultThemeFullName()
+ )
+ );
+
+ nicknameTextField.setText(client.getNickName());
+
+ if(client.getPlatform() == com.stream_pi.util.platform.Platform.ANDROID)
+ {
+ startupWindowHeightInputBox.setVisible(false);
+ startupWindowWidthInputBox.setVisible(false);
+ }
+
+ platformLabel.setText("Platform : "+client.getPlatform().getUIName());
+
+ startupWindowWidthTextField.setText(client.getStartupDisplayWidth()+"");
+ startupWindowHeightTextField.setText(client.getStartupDisplayHeight()+"");
+
+ socketConnectionLabel.setText(client.getRemoteSocketAddress().toString().substring(1)); //substring removes the `/`
+
+ nickNameLabel.setText(client.getNickName());
+
+ versionLabel.setText(client.getReleaseStatus().getUIName()+" "+client.getVersion().getText());
+
+ //add profiles
+ for(ClientProfile clientProfile : client.getAllClientProfiles())
+ {
+ TitledPane titledPane = new TitledPane();
+ titledPane.setText(clientProfile.getName());
+
+ ClientProfileVBox clientProfileVBox = new ClientProfileVBox(clientProfile);
+
+ clientProfileVBox.getRemoveButton().setOnAction(event -> onProfileDeleteButtonClicked(clientProfileVBox, titledPane));
+
+ titledPane.setContent(clientProfileVBox);
+
+ clientProfileVBoxes.add(clientProfileVBox);
+
+ profilesAccordion.getPanes().add(titledPane);
+ }
+ }
+
+ public void onNewProfileButtonClicked()
+ {
+ ClientProfile clientProfile = new ClientProfile(
+ "Untitled Profile",
+ 3,
+ 3,
+ 100,
+ 5
+ );
+
+
+ ClientProfileVBox clientProfileVBox = new ClientProfileVBox(clientProfile);
+ TitledPane titledPane = new TitledPane();
+ titledPane.setContent(clientProfileVBox);
+ titledPane.setText(clientProfile.getName());
+
+ clientProfileVBox.getRemoveButton().setOnAction(event -> onProfileDeleteButtonClicked(clientProfileVBox, titledPane));
+
+ clientProfileVBoxes.add(clientProfileVBox);
+
+ profilesAccordion.getPanes().add(titledPane);
+ }
+
+ public void onProfileDeleteButtonClicked(ClientProfileVBox clientProfileVBox, TitledPane titledPane)
+ {
+ if(clientProfileVBoxes.size() == 1)
+ {
+ exceptionAndAlertHandler.handleMinorException(new MinorException("Only one",
+ "You cannot delete all profiles"));
+ }
+ else
+ {
+ if(profilesComboBox.getSelectionModel().getSelectedItem().getID().equals(clientProfileVBox.getClientProfile().getID()))
+ {
+ exceptionAndAlertHandler.handleMinorException(new MinorException("Default",
+ "You cannot delete default profile. Change to another one to delete this."));
+ }
+ else
+ {
+ clientProfileVBoxes.remove(clientProfileVBox);
+ profilesComboBox.getItems().remove(clientProfileVBox.getClientProfile());
+
+ profilesAccordion.getPanes().remove(titledPane);
+ }
+ }
+ }
+ }
+
+ public class ClientProfileVBox extends VBox
+ {
+ private TextField nameTextField;
+
+ public String getName()
+ {
+ return nameTextField.getText();
+ }
+
+ private TextField rowsTextField;
+
+ public String getRows()
+ {
+ return rowsTextField.getText();
+ }
+
+ private TextField colsTextField;
+
+ public String getCols()
+ {
+ return colsTextField.getText();
+ }
+
+ private TextField actionSizeTextField;
+
+ public String getActionSize()
+ {
+ return actionSizeTextField.getText();
+ }
+
+ private TextField actionGapTextField;
+
+ public String getActionGap()
+ {
+ return actionGapTextField.getText();
+ }
+
+ private Button removeButton;
+
+ private ClientProfile clientProfile;
+
+ public String getRealName()
+ {
+ return clientProfile.getName();
+ }
+
+ public ClientProfileVBox(ClientProfile clientProfile)
+ {
+ this.clientProfile = clientProfile;
+
+ initUI();
+ loadValues(clientProfile);
+ }
+
+ public void initUI()
+ {
+ setPadding(new Insets(5.0));
+ setSpacing(10.0);
+
+ nameTextField = new TextField();
+ rowsTextField = new TextField();
+ colsTextField = new TextField();
+ actionSizeTextField = new TextField();
+ actionGapTextField = new TextField();
+
+ removeButton = new Button("Remove");
+
+ HBox hBox = new HBox(removeButton);
+ hBox.setAlignment(Pos.CENTER_RIGHT);
+
+
+ getChildren().addAll(
+ new HBoxInputBox("Name ", nameTextField),
+ new HBoxInputBox("Columns", rowsTextField),
+ new HBoxInputBox("Rows", colsTextField),
+ new HBoxInputBox("action Size", actionSizeTextField),
+ new HBoxInputBox("action Gap", actionGapTextField),
+ hBox
+ );
+ }
+
+ public Button getRemoveButton()
+ {
+ return removeButton;
+ }
+
+ public void loadValues(ClientProfile clientProfile)
+ {
+ nameTextField.setText(clientProfile.getName());
+
+ rowsTextField.setText(clientProfile.getRows()+"");
+ colsTextField.setText(clientProfile.getCols()+"");
+
+ actionSizeTextField.setText(clientProfile.getActionSize()+"");
+ actionGapTextField.setText(clientProfile.getActionGap()+"");
+ }
+
+ public ClientProfile getClientProfile()
+ {
+ clientProfile.setActionGap(Integer.parseInt(actionGapTextField.getText()));
+ clientProfile.setActionSize(Integer.parseInt(actionSizeTextField.getText()));
+ clientProfile.setRows(Integer.parseInt(rowsTextField.getText()));
+ clientProfile.setCols(Integer.parseInt(colsTextField.getText()));
+ clientProfile.setName(nameTextField.getText());
+
+ return clientProfile;
+ }
+ }
+
+
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/settings/GeneralSettings.java
@@ -0,0 +1,484 @@
+package com.stream_pi.server.window.settings;
+
+import com.stream_pi.server.connection.ServerListener;
+import com.stream_pi.server.io.Config;
+import com.stream_pi.server.window.ExceptionAndAlertHandler;
+import com.stream_pi.server.info.ServerInfo;
+
+import com.stream_pi.util.alert.StreamPiAlert;
+import com.stream_pi.util.alert.StreamPiAlertType;
+import com.stream_pi.util.exception.MinorException;
+import com.stream_pi.util.exception.SevereException;
+import com.stream_pi.util.startatboot.SoftwareType;
+import com.stream_pi.util.startatboot.StartAtBoot;
+import com.stream_pi.util.version.Version;
+import javafx.application.HostServices;
+import javafx.application.Platform;
+import javafx.concurrent.Task;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.control.*;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.ScrollPane;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.*;
+import javafx.stage.DirectoryChooser;
+import org.json.JSONObject;
+import org.kordamp.ikonli.javafx.FontIcon;
+
+import java.awt.SystemTray;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.logging.Logger;
+
+public class GeneralSettings extends ScrollPane {
+
+ private final TextField serverNameTextField;
+ private final TextField portTextField;
+ private final TextField pluginsPathTextField;
+ private final TextField themesPathTextField;
+ private final TextField actionGridPaneActionBoxSize;
+ private final TextField actionGridPaneActionBoxGap;
+ private final ToggleButton startOnBootToggleButton;
+ private final ToggleButton closeOnXToggleButton;
+ private final Button saveButton;
+ private final Button checkForUpdatesButton;
+
+
+ private Logger logger;
+
+ private ExceptionAndAlertHandler exceptionAndAlertHandler;
+
+ private ServerListener serverListener;
+
+ private HostServices hostServices;
+
+ public GeneralSettings(ExceptionAndAlertHandler exceptionAndAlertHandler, ServerListener serverListener, HostServices hostServices)
+ {
+ this.hostServices = hostServices;
+
+ getStyleClass().add("general_settings_scroll_pane");
+
+
+ this.exceptionAndAlertHandler = exceptionAndAlertHandler;
+ this.serverListener = serverListener;
+
+ logger = Logger.getLogger(GeneralSettings.class.getName());
+
+ setHbarPolicy(ScrollBarPolicy.NEVER);
+
+ serverNameTextField = new TextField();
+
+ portTextField = new TextField();
+
+ pluginsPathTextField = new TextField();
+
+ themesPathTextField = new TextField();
+
+ actionGridPaneActionBoxSize = new TextField();
+ actionGridPaneActionBoxGap = new TextField();
+
+ startOnBootToggleButton = new ToggleButton("Start on Boot");
+ closeOnXToggleButton = new ToggleButton("Quit On window Close");
+
+ checkForUpdatesButton = new Button("Check for updates");
+ checkForUpdatesButton.setOnAction(event->checkForUpdates());
+
+
+ VBox vBox = new VBox();
+ vBox.prefWidthProperty().bind(widthProperty());
+ vBox.setAlignment(Pos.CENTER);
+ vBox.setSpacing(5);
+
+ vBox.getChildren().addAll(
+ getUIInputBox("Server Name", serverNameTextField),
+ getUIInputBox("Port", portTextField),
+ getUIInputBox("action Grid Pane action Box Size", actionGridPaneActionBoxSize),
+ getUIInputBox("action Grid Pane action Box Gap", actionGridPaneActionBoxGap),
+ getUIInputBoxWithDirectoryChooser("Plugins Path", pluginsPathTextField),
+ getUIInputBoxWithDirectoryChooser("Themes Path", themesPathTextField)
+ );
+
+ serverNameTextField.setPrefWidth(200);
+
+ HBox toggleButtons = new HBox(closeOnXToggleButton, startOnBootToggleButton);
+ toggleButtons.setSpacing(10.0);
+ VBox.setMargin(toggleButtons, new Insets(30, 0 , 0,0));
+ toggleButtons.setAlignment(Pos.CENTER);
+
+ saveButton = new Button("Save");
+ saveButton.setOnAction(event->save());
+
+ vBox.getChildren().addAll(toggleButtons, checkForUpdatesButton, saveButton);
+
+ vBox.setPadding(new Insets(10));
+
+
+ vBox.getStyleClass().add("general_settings");
+ setContent(vBox);
+ }
+
+ private HBox getUIInputBoxWithDirectoryChooser(String labelText, TextField textField)
+ {
+ HBox hBox = getUIInputBox(labelText, textField);
+ hBox.setSpacing(5.0);
+
+ TextField tf = (TextField) hBox.getChildren().get(2);
+ tf.setPrefWidth(300);
+ tf.setDisable(true);
+
+
+ Button button = new Button();
+ FontIcon fontIcon = new FontIcon("far-folder");
+ button.setGraphic(fontIcon);
+
+ button.setOnAction(event -> {
+ DirectoryChooser directoryChooser = new DirectoryChooser();
+
+
+ try {
+ File selectedDirectory = directoryChooser.showDialog(getScene().getWindow());
+
+ textField.setText(selectedDirectory.getAbsolutePath());
+ }
+ catch (NullPointerException e)
+ {
+ logger.info("No folder selected");
+ }
+ });
+
+ hBox.getChildren().add(button);
+
+
+ return hBox;
+ }
+
+ private HBox getUIInputBox(String labelText, TextField textField)
+ {
+ textField.setPrefWidth(100);
+
+ Label label = new Label(labelText);
+ Region region = new Region();
+ HBox.setHgrow(region, Priority.ALWAYS);
+
+
+ return new HBox(label, region, textField);
+ }
+
+
+
+ public void loadDataFromConfig() throws SevereException {
+ Config config = Config.getInstance();
+
+ Platform.runLater(()->
+ {
+ serverNameTextField.setText(config.getServerName());
+ portTextField.setText(config.getPort()+"");
+ pluginsPathTextField.setText(config.getPluginsPath());
+ themesPathTextField.setText(config.getThemesPath());
+ actionGridPaneActionBoxSize.setText(config.getActionGridActionSize()+"");
+ actionGridPaneActionBoxGap.setText(config.getActionGridActionGap()+"");
+
+ closeOnXToggleButton.setSelected(config.getCloseOnX());
+ startOnBootToggleButton.setSelected(config.getStartOnBoot());
+ });
+ }
+
+ public void save()
+ {
+ new Thread(new Task<Void>() {
+ @Override
+ protected Void call()
+ {
+ try {
+ boolean toBeReloaded = false;
+ boolean dashToBeReRendered = false;
+
+ Platform.runLater(()->{
+ saveButton.setDisable(true);
+
+ serverNameTextField.setDisable(true);
+ portTextField.setDisable(true);
+
+ closeOnXToggleButton.setDisable(true);
+ startOnBootToggleButton.setDisable(true);
+ });
+
+ String serverNameStr = serverNameTextField.getText();
+ String serverPortStr = portTextField.getText();
+ String pluginsPathStr = pluginsPathTextField.getText();
+ String themesPathStr = themesPathTextField.getText();
+
+ String actionGridActionBoxSize = actionGridPaneActionBoxSize.getText();
+ String actionGridActionBoxGap = actionGridPaneActionBoxGap.getText();
+
+ boolean closeOnX = closeOnXToggleButton.isSelected();
+ boolean startOnBoot = startOnBootToggleButton.isSelected();
+
+ Config config = Config.getInstance();
+
+ StringBuilder errors = new StringBuilder();
+
+
+ if(serverNameStr.isBlank())
+ {
+ errors.append("* Server Name cannot be blank.\n");
+ }
+ else
+ {
+ if(!config.getServerName().equals(serverNameStr))
+ {
+ toBeReloaded = true;
+ }
+ }
+
+
+ int serverPort=-1;
+ try {
+ serverPort = Integer.parseInt(serverPortStr);
+
+ if (serverPort < 1024)
+ errors.append("* Server Port must be more than 1024");
+
+ if(config.getPort()!=serverPort)
+ {
+ toBeReloaded = true;
+ }
+ }
+ catch (NumberFormatException e)
+ {
+ errors.append("* Server Port must be integer.\n");
+ }
+
+
+ int actionSize=-1;
+ try {
+ actionSize = Integer.parseInt(actionGridActionBoxSize);
+
+ if(config.getActionGridActionSize() != actionSize)
+ {
+ dashToBeReRendered = true;
+ }
+ }
+ catch (NumberFormatException e)
+ {
+ errors.append("* action Size must be integer.\n");
+ }
+
+
+ int actionGap=-1;
+ try {
+ actionGap = Integer.parseInt(actionGridActionBoxGap);
+
+ if(config.getActionGridActionGap() != actionGap)
+ {
+ dashToBeReRendered = true;
+ }
+ }
+ catch (NumberFormatException e)
+ {
+ errors.append("* action Gap must be integer.\n");
+ }
+
+ if(pluginsPathStr.isBlank())
+ {
+ errors.append("* Plugins Path must not be blank.\n");
+ }
+ else
+ {
+ if(!config.getPluginsPath().equals(pluginsPathStr))
+ {
+ toBeReloaded = true;
+ }
+ }
+
+ if(themesPathStr.isBlank())
+ {
+ errors.append("* Themes Path must not be blank.\n");
+ }
+ else
+ {
+ if(!config.getThemesPath().equals(themesPathStr))
+ {
+ toBeReloaded = true;
+ }
+ }
+
+ if(!errors.toString().isEmpty())
+ {
+ throw new MinorException("settings", "Please rectify the following errors and try again :\n"+errors.toString());
+ }
+
+ if(config.getStartOnBoot() != startOnBoot)
+ {
+ if(ServerInfo.getInstance().getRunnerFileName() == null)
+ {
+ new StreamPiAlert("Uh Oh", "No Runner File Name Specified as startup arguments. Cant set run at boot.", StreamPiAlertType.ERROR).show();
+ startOnBoot = false;
+ }
+ else
+ {
+ StartAtBoot startAtBoot = new StartAtBoot(SoftwareType.SERVER, ServerInfo.getInstance().getPlatformType());
+ if(startOnBoot)
+ {
+ startAtBoot.create(new File(ServerInfo.getInstance().getRunnerFileName()));
+ }
+ else
+ {
+ boolean result = startAtBoot.delete();
+ if(!result)
+ new StreamPiAlert("Uh Oh!", "Unable to delete starter file", StreamPiAlertType.ERROR).show();
+ }
+ }
+ }
+
+ if(!closeOnX)
+ {
+ System.out.println("XYZ");
+ if(!SystemTray.isSupported())
+ {
+ StreamPiAlert alert = new StreamPiAlert("Not Supported", "Tray System not supported on this platform ", StreamPiAlertType.ERROR);
+ alert.show();
+
+ closeOnX = true;
+ }
+ else
+ {
+ System.out.println("YES");
+ }
+ }
+
+ config.setServerName(serverNameStr);
+ config.setServerPort(serverPort);
+ config.setActionGridGap(actionGap);
+ config.setActionGridSize(actionSize);
+ config.setPluginsPath(pluginsPathStr);
+ config.setThemesPath(themesPathStr);
+
+ config.setCloseOnX(closeOnX);
+ config.setStartupOnBoot(startOnBoot);
+
+ config.save();
+
+
+ loadDataFromConfig();
+
+ if(toBeReloaded)
+ {
+ new StreamPiAlert("Restart","Restart to see changes", StreamPiAlertType.INFORMATION).show();
+ }
+
+ if(dashToBeReRendered)
+ {
+ serverListener.clearTemp();
+ }
+ }
+ catch (MinorException e)
+ {
+ exceptionAndAlertHandler.handleMinorException(e);
+ }
+ catch (SevereException e)
+ {
+ exceptionAndAlertHandler.handleSevereException(e);
+ }
+ finally {
+ Platform.runLater(()->{
+ saveButton.setDisable(false);
+
+ serverNameTextField.setDisable(false);
+ portTextField.setDisable(false);
+
+ closeOnXToggleButton.setDisable(false);
+ startOnBootToggleButton.setDisable(false);
+ });
+ }
+ return null;
+ }
+ }).start();
+ }
+
+ public void checkForUpdates()
+ {
+ new Thread(new Task<Void>()
+ {
+ @Override
+ protected Void call() throws Exception {
+ try
+ {
+ Platform.runLater(()->checkForUpdatesButton.setDisable(true));
+
+
+ String jsonRaw = readUrl("https://stream-pi.com/API/get_latest.php?TYPE=SERVER");
+
+ System.out.println(jsonRaw);
+
+ JSONObject jsonObject = new JSONObject(jsonRaw);
+
+ String latestVersionRaw = jsonObject.getString("Version");
+ String releasePage = jsonObject.getString("Release Page");
+
+ Version latestVersion = new Version(latestVersionRaw);
+ Version currentVersion = ServerInfo.getInstance().getVersion();
+
+ if(latestVersion.isBiggerThan(currentVersion))
+ {
+ VBox vBox = new VBox();
+
+ Hyperlink urlLabel = new Hyperlink(releasePage);
+ urlLabel.setOnAction(event->hostServices.showDocument(releasePage));
+
+ Label label = new Label(
+ "New Version "+latestVersionRaw+" Available.\n" +
+ "Current Version "+currentVersion.getText()+".\n"+
+ "Changelog and install instructions are included in the release page.\n" +
+ "It is recommended to update to ensure maximum stability and least bugs.");
+ label.setWrapText(true);
+
+ vBox.setSpacing(5);
+ vBox.getChildren().addAll(
+ urlLabel,
+ label
+ );
+
+ new StreamPiAlert("New Update Available!", StreamPiAlertType.INFORMATION, vBox).show();;
+ }
+ else
+ {
+ new StreamPiAlert("Up to Date", "Server is upto date. ("+currentVersion.getText()+")", StreamPiAlertType.INFORMATION).show();;
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ new StreamPiAlert("Uh Oh", "Update Check Failed. API Error/Network issue.", StreamPiAlertType.WARNING).show();;
+ }
+ finally
+ {
+ Platform.runLater(()->checkForUpdatesButton.setDisable(false));
+ }
+ return null;
+ }
+ }).start();;
+ }
+
+ private String readUrl(String urlString) throws Exception {
+ BufferedReader reader = null;
+ try {
+ URL url = new URL(urlString);
+ reader = new BufferedReader(new InputStreamReader(url.openStream()));
+ StringBuffer buffer = new StringBuffer();
+ int read;
+ char[] chars = new char[1024];
+ while ((read = reader.read(chars)) != -1)
+ buffer.append(chars, 0, read);
+
+ return buffer.toString();
+ } finally {
+ if (reader != null)
+ reader.close();
+ }
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/settings/PluginsSettings.java
@@ -0,0 +1,384 @@
+package com.stream_pi.server.window.settings;
+
+import com.stream_pi.server.uipropertybox.UIPropertyBox;
+import com.stream_pi.actionapi.actionproperty.property.ControlType;
+import com.stream_pi.actionapi.actionproperty.property.Property;
+import com.stream_pi.actionapi.actionproperty.property.Type;
+import com.stream_pi.actionapi.normalaction.NormalAction;
+import com.stream_pi.server.action.NormalActionPlugins;
+import com.stream_pi.server.connection.ServerListener;
+import com.stream_pi.server.window.ExceptionAndAlertHandler;
+import com.stream_pi.util.exception.MinorException;
+import com.stream_pi.util.uihelper.SpaceFiller;
+import com.stream_pi.util.uihelper.SpaceFiller.FillerType;
+
+import org.kordamp.ikonli.javafx.FontIcon;
+
+import javafx.application.HostServices;
+import javafx.application.Platform;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.Node;
+import javafx.scene.control.*;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.Region;
+import javafx.scene.layout.VBox;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+public class PluginsSettings extends VBox {
+
+ private VBox pluginsSettingsVBox;
+
+ private ServerListener serverListener;
+
+ private Logger logger;
+
+ private ExceptionAndAlertHandler exceptionAndAlertHandler;
+
+ private HostServices hostServices;
+
+ public PluginsSettings(ExceptionAndAlertHandler exceptionAndAlertHandler, HostServices hostServices)
+ {
+ getStyleClass().add("plugins_settings");
+
+ this.hostServices = hostServices;
+ this.exceptionAndAlertHandler = exceptionAndAlertHandler;
+ pluginProperties = new ArrayList<>();
+ logger = Logger.getLogger(PluginsSettings.class.getName());
+
+ setPadding(new Insets(10));
+
+ pluginsSettingsVBox = new VBox();
+ pluginsSettingsVBox.setSpacing(10.0);
+ pluginsSettingsVBox.setAlignment(Pos.TOP_CENTER);
+
+ ScrollPane scrollPane = new ScrollPane();
+
+ scrollPane.getStyleClass().add("plugins_settings_scroll_pane");
+ scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
+ scrollPane.maxWidthProperty().bind(widthProperty().multiply(0.8));
+
+ pluginsSettingsVBox.prefWidthProperty().bind(scrollPane.widthProperty().subtract(25));
+ scrollPane.setContent(pluginsSettingsVBox);
+
+ VBox.setVgrow(scrollPane, Priority.ALWAYS);
+
+ setAlignment(Pos.TOP_CENTER);
+
+
+ saveButton = new Button("Save");
+
+ saveButton.setOnAction(event -> onSaveButtonClicked());
+
+
+ HBox hBox = new HBox(saveButton);
+ hBox.setAlignment(Pos.CENTER_RIGHT);
+
+ getChildren().addAll(scrollPane, hBox);
+
+ }
+
+ private Button saveButton;
+
+ public void onSaveButtonClicked()
+ {
+ try {
+ //form validation
+ StringBuilder finalErrors = new StringBuilder();
+
+ for (PluginProperties p : pluginProperties)
+ {
+ StringBuilder errors = new StringBuilder();
+ for(int j = 0; j < p.getServerPropertyUIBox().size(); j++)
+ {
+ UIPropertyBox serverProperty = p.getServerPropertyUIBox().get(j);
+ Node controlNode = serverProperty.getControlNode();
+
+ if (serverProperty.getControlType() == ControlType.TEXT_FIELD)
+ {
+ String value = ((TextField) controlNode).getText();
+ if(serverProperty.getType() == Type.INTEGER)
+ {
+ try
+ {
+ Integer.parseInt(value);
+ }
+ catch (NumberFormatException e)
+ {
+ errors.append(" -> ").append(serverProperty.getDisplayName()).append(" must be integer.\n");
+ }
+ }
+ else
+ {
+ if(value.isBlank() && !serverProperty.isCanBeBlank())
+ errors.append(" -> ").append(serverProperty.getDisplayName()).append(" cannot be blank.\n");
+ }
+ }
+ }
+
+ if(!errors.toString().isBlank())
+ {
+ finalErrors.append(" * ").append(p.getName()).append("\n").append(errors.toString()).append("\n");
+ }
+ }
+
+ if(!finalErrors.toString().isEmpty())
+ {
+ throw new MinorException("Form Validation Errors",
+ "Please rectify the following errors and try again \n"+finalErrors.toString());
+ }
+
+ //save
+ for (PluginProperties pp : pluginProperties) {
+ for (int j = 0; j < pp.getServerPropertyUIBox().size(); j++) {
+
+
+ UIPropertyBox serverProperty = pp.getServerPropertyUIBox().get(j);
+
+ String rawValue = serverProperty.getRawValue();
+
+ NormalActionPlugins.getInstance().getActionFromIndex(pp.getIndex())
+ .getServerProperties().get()
+ .get(serverProperty.getIndex()).setRawValue(rawValue);
+ }
+ }
+
+
+ NormalActionPlugins.getInstance().saveServerSettings();
+
+ NormalActionPlugins.getInstance().initPlugins();
+ }
+ catch (MinorException e)
+ {
+ e.printStackTrace();
+ exceptionAndAlertHandler.handleMinorException(e);
+ }
+ }
+
+ private ArrayList<PluginProperties> pluginProperties;
+
+
+ public void showPluginInitError()
+ {
+ Platform.runLater(()->{
+ pluginsSettingsVBox.getChildren().add(new Label("Plugin init error. Resolve issues and restart."));
+ saveButton.setVisible(false);
+ });
+ }
+
+ public void loadPlugins() throws MinorException {
+
+ pluginProperties.clear();
+
+ List<NormalAction> actions = NormalActionPlugins.getInstance().getPlugins();
+
+ System.out.println("asdasdasdasd"+actions.size());
+
+ Platform.runLater(()-> pluginsSettingsVBox.getChildren().clear());
+
+ if(actions.size() == 0)
+ {
+ Platform.runLater(()->{
+ pluginsSettingsVBox.getChildren().add(new Label("No Plugins Installed."));
+ saveButton.setVisible(false);
+ });
+ return;
+ }
+ else
+ {
+ Platform.runLater(()->saveButton.setVisible(true));
+ }
+
+
+ for(int i = 0; i<actions.size(); i++)
+ {
+ NormalAction action = actions.get(i);
+
+ if(!action.isVisibleInServerSettingsPane())
+ continue;
+
+
+ Label headingLabel = new Label(action.getName());
+ headingLabel.getStyleClass().add("settings_plugins_each_action_heading");
+
+ HBox headerHBox = new HBox(headingLabel);
+
+
+ if (action.getHelpLink()!=null)
+ {
+ Button helpButton = new Button();
+ FontIcon questionIcon = new FontIcon("fas-question");
+ questionIcon.getStyleClass().add("settings_plugins_plugin_help_icon");
+ helpButton.setGraphic(questionIcon);
+ helpButton.setOnAction(event -> hostServices.showDocument(action.getHelpLink()));
+
+ headerHBox.getChildren().addAll(new SpaceFiller(FillerType.HBox),helpButton);
+ }
+
+
+
+ Label authorLabel = new Label(action.getAuthor());
+
+ Label moduleLabel = new Label(action.getModuleName());
+
+ Label versionLabel = new Label("Version : "+action.getVersion().getText());
+
+ VBox serverPropertiesVBox = new VBox();
+ serverPropertiesVBox.setSpacing(10.0);
+
+ List<Property> serverProperties = action.getServerProperties().get();
+
+ ArrayList<UIPropertyBox> serverPropertyArrayList = new ArrayList<>();
+
+
+ for(int j =0; j<serverProperties.size(); j++)
+ {
+ Property eachProperty = serverProperties.get(j);
+
+ if(!eachProperty.isVisible())
+ continue;
+
+
+ Label label = new Label(eachProperty.getDisplayName());
+
+ Region region = new Region();
+ HBox.setHgrow(region, Priority.ALWAYS);
+
+ HBox hBox = new HBox(label, new SpaceFiller(SpaceFiller.FillerType.HBox));
+ //hBox.setId(j+"");
+
+ Node controlNode = null;
+
+ if(eachProperty.getControlType() == ControlType.COMBO_BOX)
+ {
+ ComboBox<String> comboBox = new ComboBox<>();
+ comboBox.getItems().addAll(eachProperty.getListValue());
+ comboBox.getSelectionModel().select(eachProperty.getSelectedIndex());
+ hBox.getChildren().add(comboBox);
+
+ controlNode = comboBox;
+ }
+ else if(eachProperty.getControlType() == ControlType.TEXT_FIELD)
+ {
+ TextField textField = new TextField(eachProperty.getRawValue());
+
+ hBox.getChildren().add(textField);
+
+ controlNode = textField;
+ }
+ else if(eachProperty.getControlType() == ControlType.TOGGLE)
+ {
+ ToggleButton toggleButton = new ToggleButton();
+ toggleButton.setSelected(eachProperty.getBoolValue());
+
+ if(eachProperty.getBoolValue())
+ toggleButton.setText("ON");
+ else
+ toggleButton.setText("OFF");
+
+ toggleButton.selectedProperty().addListener((observableValue, aBoolean, t1) -> {
+ if(t1)
+ toggleButton.setText("ON");
+ else
+ toggleButton.setText("OFF");
+ });
+
+ hBox.getChildren().add(toggleButton);
+
+ controlNode = toggleButton;
+ }
+ else if(eachProperty.getControlType() == ControlType.SLIDER_DOUBLE)
+ {
+ Slider slider = new Slider();
+ slider.setValue(eachProperty.getDoubleValue());
+ slider.setMax(eachProperty.getMaxDoubleValue());
+ slider.setMin(eachProperty.getMinDoubleValue());
+
+ hBox.getChildren().add(slider);
+
+ controlNode = slider;
+ }
+ else if(eachProperty.getControlType() == ControlType.SLIDER_INTEGER)
+ {
+ Slider slider = new Slider();
+ slider.setValue(eachProperty.getIntValue());
+
+ slider.setMax(eachProperty.getMaxIntValue());
+ slider.setMin(eachProperty.getMinIntValue());
+ slider.setBlockIncrement(1.0);
+ slider.setSnapToTicks(true);
+
+ hBox.getChildren().add(slider);
+
+ controlNode = slider;
+ }
+
+
+ UIPropertyBox serverProperty = new UIPropertyBox(j, eachProperty.getDisplayName(), controlNode, eachProperty.getControlType(), eachProperty.getType(), eachProperty.isCanBeBlank());
+
+ serverPropertyArrayList.add(serverProperty);
+
+ serverPropertiesVBox.getChildren().add(hBox);
+
+ }
+
+ PluginProperties pp = new PluginProperties(i, serverPropertyArrayList, action.getName());
+
+ pluginProperties.add(pp);
+
+
+
+ Region region1 = new Region();
+ region1.setPrefHeight(5);
+
+
+ Platform.runLater(()->{
+ VBox vBox = new VBox();
+ vBox.setSpacing(5.0);
+ vBox.getChildren().addAll(headerHBox, authorLabel, moduleLabel, versionLabel, serverPropertiesVBox);
+
+ if(action.getButtonBar()!=null)
+ vBox.getChildren().add(new HBox(new SpaceFiller(SpaceFiller.FillerType.HBox), action.getButtonBar()));
+
+ vBox.getChildren().add(region1);
+ //vBox.setId(i+"");
+
+ vBox.getStyleClass().add("settings_plugins_each_action");
+
+ pluginsSettingsVBox.getChildren().add(vBox);
+
+ });
+ }
+ }
+
+ public class PluginProperties
+ {
+ private int index;
+ private ArrayList<UIPropertyBox> serverProperty;
+ private String name;
+
+ public PluginProperties(int index, ArrayList<UIPropertyBox> serverProperty, String name)
+ {
+ this.index = index;
+ this.serverProperty = serverProperty;
+ this.name = name;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public ArrayList<UIPropertyBox> getServerPropertyUIBox() {
+ return serverProperty;
+ }
+ }
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/settings/SettingsBase.java
@@ -0,0 +1,100 @@
+package com.stream_pi.server.window.settings;
+
+import com.stream_pi.server.connection.ServerListener;
+import com.stream_pi.server.window.ExceptionAndAlertHandler;
+import javafx.application.HostServices;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.CacheHint;
+import javafx.scene.control.*;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.VBox;
+
+public class SettingsBase extends VBox {
+
+ private TabPane tabPane;
+
+ private GeneralSettings generalSettings;
+ private PluginsSettings pluginsSettings;
+ private ThemesSettings themesSettings;
+ private ClientsSettings clientsSettings;
+
+ private Button closeButton;
+
+ private HostServices hostServices;
+ private ExceptionAndAlertHandler exceptionAndAlertHandler;
+
+ public SettingsBase(HostServices hostServices, ExceptionAndAlertHandler exceptionAndAlertHandler,
+ ServerListener serverListener)
+ {
+ this.exceptionAndAlertHandler = exceptionAndAlertHandler;
+ this.hostServices = hostServices;
+
+ tabPane = new TabPane();
+ tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
+ VBox.setVgrow(tabPane, Priority.ALWAYS);
+
+ Tab generalSettingsTab = new Tab("General");
+ generalSettings = new GeneralSettings(exceptionAndAlertHandler, serverListener, hostServices);
+ generalSettingsTab.setContent(generalSettings);
+
+ Tab pluginsSettingsTab = new Tab("Plugins");
+ pluginsSettings = new PluginsSettings(exceptionAndAlertHandler, hostServices);
+ pluginsSettingsTab.setContent(pluginsSettings);
+
+ Tab themesSettingsTab = new Tab("Themes");
+ themesSettings = new ThemesSettings(hostServices);
+ themesSettingsTab.setContent(themesSettings);
+
+ Tab clientsSettingsTab = new Tab("Clients");
+ clientsSettings = new ClientsSettings(exceptionAndAlertHandler, serverListener);
+ clientsSettingsTab.setContent(clientsSettings);
+
+
+ Tab aboutTab = new Tab("About");
+ aboutTab.setContent(new About(hostServices));
+
+ tabPane.getTabs().addAll(generalSettingsTab, pluginsSettingsTab, themesSettingsTab, clientsSettingsTab, aboutTab);
+
+ setAlignment(Pos.TOP_RIGHT);
+
+ closeButton = new Button("Close");
+ VBox.setMargin(closeButton, new Insets(10.0));
+
+ getChildren().addAll(tabPane, closeButton);
+
+ setCache(true);
+ setCacheHint(CacheHint.SPEED);
+ }
+
+ public void setDefaultTabToGeneral()
+ {
+ tabPane.getSelectionModel().selectFirst();
+ }
+
+ public Button getCloseButton()
+ {
+ return closeButton;
+ }
+
+ public GeneralSettings getGeneralSettings()
+ {
+ return generalSettings;
+ }
+
+ public PluginsSettings getPluginsSettings()
+ {
+ return pluginsSettings;
+ }
+
+ public ThemesSettings getThemesSettings()
+ {
+ return themesSettings;
+ }
+
+ public ClientsSettings getClientsSettings()
+ {
+ return clientsSettings;
+ }
+
+}
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/window/settings/ThemesSettings.java
@@ -0,0 +1,190 @@
+package com.stream_pi.server.window.settings;
+
+import com.stream_pi.server.controller.Controller;
+import com.stream_pi.server.io.Config;
+import com.stream_pi.themeapi.Theme;
+import com.stream_pi.themeapi.Themes;
+import com.stream_pi.util.exception.SevereException;
+import com.stream_pi.util.uihelper.SpaceFiller;
+import javafx.application.HostServices;
+import javafx.application.Platform;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.control.*;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.Region;
+import javafx.scene.layout.VBox;
+import org.kordamp.ikonli.javafx.FontIcon;
+
+import java.util.ArrayList;
+import java.util.logging.Logger;
+
+public class ThemesSettings extends VBox
+{
+ private VBox themesSettingsVBox;
+
+ private Controller controller;
+
+ private Logger logger;
+ private HostServices hostServices;
+
+ public ThemesSettings(HostServices hostServices)
+ {
+ this.hostServices = hostServices;
+ getStyleClass().add("themes_settings");
+ logger = Logger.getLogger(ThemesSettings.class.getName());
+
+ setPadding(new Insets(10));
+
+ themesSettingsVBox = new VBox();
+ themesSettingsVBox.setSpacing(10.0);
+ themesSettingsVBox.setAlignment(Pos.TOP_CENTER);
+
+ ScrollPane scrollPane = new ScrollPane();
+ scrollPane.getStyleClass().add("themes_settings_scroll_pane");
+ scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
+ scrollPane.maxWidthProperty().bind(widthProperty().multiply(0.8));
+
+ themesSettingsVBox.prefWidthProperty().bind(scrollPane.widthProperty().subtract(10));
+ scrollPane.setContent(themesSettingsVBox);
+
+ VBox.setVgrow(scrollPane, Priority.ALWAYS);
+
+ setAlignment(Pos.TOP_CENTER);
+
+ getChildren().addAll(scrollPane);
+
+ toggleButtons = new ArrayList<>();
+
+ }
+
+ public void setController(Controller controller)
+ {
+ this.controller = controller;
+ }
+
+ private Themes themes;
+ private String currentThemeFullName;
+
+ public void setThemes(Themes themes)
+ {
+ this.themes = themes;
+ }
+
+ public void setCurrentThemeFullName(String currentThemeFullName)
+ {
+ this.currentThemeFullName = currentThemeFullName;
+ }
+
+ private ArrayList<ToggleButton> toggleButtons;
+
+ public void loadThemes()
+ {
+ toggleButtons.clear();
+
+ Platform.runLater(()-> themesSettingsVBox.getChildren().clear());
+
+
+ for(int i = 0; i<themes.getThemeList().size(); i++)
+ {
+ Theme theme = themes.getThemeList().get(i);
+
+ Label shortNameLabel = new Label(theme.getShortName());
+ shortNameLabel.getStyleClass().add("settings_themes_each_theme_heading");
+
+ Label authorLabel = new Label(theme.getAuthor());
+
+ Label fullNameLabel = new Label(theme.getFullName());
+
+
+ HBox topRowHBox = new HBox(shortNameLabel);
+
+ if(theme.getWebsite() != null)
+ {
+ Button helpButton = new Button();
+ FontIcon questionIcon = new FontIcon("fas-question");
+ questionIcon.getStyleClass().add("settings_themes_theme_help_icon");
+ helpButton.setGraphic(questionIcon);
+ helpButton.setOnAction(event -> hostServices.showDocument(theme.getWebsite()));
+
+ topRowHBox.getChildren().addAll(new SpaceFiller(SpaceFiller.FillerType.HBox), helpButton);
+ }
+
+
+
+ Label versionLabel = new Label("Version : "+theme.getVersion().getText());
+
+ ToggleButton toggleButton = new ToggleButton();
+
+ toggleButton.setSelected(theme.getFullName().equals(currentThemeFullName));
+ toggleButton.setId(theme.getFullName());
+
+
+ if(theme.getFullName().equals(currentThemeFullName))
+ {
+ toggleButton.setText("ON");
+ toggleButton.setSelected(true);
+ toggleButton.setDisable(true);
+ }
+ else
+ {
+ toggleButton.setText("OFF");
+ }
+
+ toggleButton.setOnAction(event -> {
+ ToggleButton toggleButton1 = (ToggleButton) event.getSource();
+
+
+ toggleButton.setText("ON");
+
+ try {
+ Config.getInstance().setCurrentThemeFullName(toggleButton1.getId());
+ Config.getInstance().save();
+
+
+ for(ToggleButton toggleButton2 : toggleButtons)
+ {
+ if(toggleButton2.getId().equals(Config.getInstance().getCurrentThemeFullName()))
+ {
+ toggleButton2.setDisable(true);
+ toggleButton2.setText("ON");
+ toggleButton2.setSelected(true);
+ }
+ else
+ {
+ toggleButton2.setDisable(false);
+ toggleButton2.setText("OFF");
+ toggleButton2.setSelected(false);
+ }
+ }
+
+ controller.initThemes();
+ }
+ catch (SevereException e)
+ {
+ controller.handleSevereException(e);
+ }
+ });
+
+ HBox hBox = new HBox(toggleButton);
+
+ Region region1 = new Region();
+ region1.setPrefHeight(5);
+
+ hBox.setAlignment(Pos.TOP_RIGHT);
+
+ VBox vBox = new VBox(topRowHBox, authorLabel, versionLabel, fullNameLabel, hBox, region1);
+ vBox.setSpacing(5.0);
+
+
+ vBox.getStyleClass().add("settings_themes_each_theme");
+
+ Platform.runLater(()->themesSettingsVBox.getChildren().add(vBox));
+
+
+ toggleButtons.add(toggleButton);
+ }
+
+ }
+}
--- 'a/src/main/java/module-info.java'
+++ b/src/main/java/module-info.java
@@ -1,10 +1,10 @@
-module com.StreamPi.Server {
- uses com.StreamPi.ActionAPI.Action.Action;
- uses com.StreamPi.ActionAPI.NormalAction.NormalAction;
-
- requires com.StreamPi.ActionAPI;
- requires com.StreamPi.Util;
- requires com.StreamPi.ThemeAPI;
+module com.stream_pi.server {
+ uses com.stream_pi.actionapi.action.Action;
+ uses com.stream_pi.actionapi.normalaction.NormalAction;
+
+ requires com.stream_pi.actionapi;
+ requires com.stream_pi.util;
+ requires com.stream_pi.themeapi;
requires org.kordamp.ikonli.javafx;
@@ -21,5 +21,5 @@ module com.StreamPi.Server {
requires org.json;
- exports com.StreamPi.Server;
+ exports com.stream_pi.server;
}
\ No newline at end of file
Binary files 'a/src/main/resources/com/StreamPi/Server/Default.obj' and /dev/null differ
Binary files 'a/src/main/resources/com/StreamPi/Server/Roboto.ttf' and /dev/null differ
Binary files 'a/src/main/resources/com/StreamPi/Server/app_icon.png' and /dev/null differ
--- 'a/src/main/resources/com/StreamPi/Server/style.css'
+++ /dev/null
@@ -1,199 +0,0 @@
-.root {
- -fx-font-family : 'Roboto';
-}
-
-.settings_about_streampi_header
-{
- -fx-font-size : 25;
-}
-
-.settings_about_donate_hyperlink
-{
- -fx-font-size : 19;
- -fx-font-weight : bold;
-}
-
-.settings_about_license_label
-{
- -fx-font-size : 16;
-}
-
-.settings_plugins_each_action, .settings_themes_each_theme, .settings_clients_each_client
-{
- -fx-border-width : 0 0 1 0;
- -fx-border-color : grey;
-}
-
-.settings_plugins_each_action_heading, .settings_themes_each_theme_heading, .settings_client_nick_name_label
-{
- -fx-font-size : 19;
-}
-
-.action_box
-{
- -fx-border-width: 1px;
- -fx-shape: "M100,100 h200 a20,20 0 0 1 20,20 v200 a20,20 0 0 1 -20,20 h-200 a20,20 0 0 1 -20,-20 v-200 a20,20 0 0 1 20,-20 z";
-}
-
-.action_box_icon_present
-{
-
-}
-
-.action_box_icon_not_present
-{
-
-}
-
-.action_box_valid
-{
- -fx-border-color: grey;
-}
-
-.action_box_invalid
-{
- -fx-border-color: red;
-}
-
-.action_box_display_text_label
-{
- -fx-font-size : 16;
- -fx-background-color : transparent;
-}
-
-.action_details_pane_action_heading_label
-{
- -fx-font-size : 16;
-}
-
-.settings_client_socket_connection_label
-{
- -fx-font-size : 16;
-}
-
-
-.alert_header
-{
- -fx-padding: 5;
-}
-
-.alert_pane
-{
- -fx-background-color : white;
- -fx-border-color : white;
- -fx-border-width : 5;
- -fx-border-radius : 5;
- -fx-background-radius : 5;
- -fx-max-width : 400;
- -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 5, 0.0 , 0.0 , 0 );
-}
-
-.alert_header_icon
-{
- -fx-icon-size : 30;
-}
-
-.alert_error_icon
-{
- -fx-icon-color: RED;
-}
-
-.alert_information_icon
-{
- -fx-icon-color: BLUE;
-}
-
-.alert_warning_icon
-{
- -fx-icon-color: #ffcc00;
-}
-
-.alert_content_pane
-{
- -fx-background-color: white;
- -fx-padding: 5;
-}
-
-.alert_pane_parent, .combobox_pane_parent
-{
- -fx-background-color : rgba(0,0,0,0.5);
-}
-
-.alert_pane_header_text
-{
- -fx-font-size: 18;
-}
-
-.alert_button_bar
-{
- -fx-background-color: white;
- -fx-alignment: CENTER_RIGHT;
- -fx-spacing: 5;
- -fx-padding: 5;
-}
-
-.alert_scroll_pane {
- -fx-background: #FFFFFF;
- -fx-border-color:#FFFFFF;
- -fx-max-height : 300;
- /*-fx-focus-color: #FFFFFF;
- -fx-faint-focus-color:#FFFFFF;*/
-}
-
-.dashboard_plugins_pane_action_icon_imageview
-{
- -fx-width:20;
- -fx-height:20;
-}
-
-.donate_request_popup_patreon_link
-{
- -fx-padding : 10 0 0 0;
- -fx-font-size : 15;
-}
-
-
-.first_time_use_pane
-{
- -fx-padding : 5;
-}
-
-.first_time_use_pane_heading_label
-{
- -fx-font-size: 20;
-}
-
-.first_time_use_pane_stackpane
-{
-
-}
-
-.first_time_use_pane_welcome
-{
-
-}
-
-.first_time_use_pane_license
-{
- -fx-spacing : 10;
-}
-
-.first_time_use_pane_final_config
-{
-
-}
-
-.first_time_use_pane_final_config_label
-{
- -fx-padding: 0 0 30 0;
-}
-
-.first_time_use_welcome_pane_welcome_label
-{
- -fx-font-size: 30;
-}
-
-.first_time_use_welcome_pane_next_to_continue_label
-{
- -fx-font-size: 15;
-}
\ No newline at end of file
Binary files /dev/null and b/src/main/resources/com/stream_pi/server/Default.obj differ
Binary files /dev/null and b/src/main/resources/com/stream_pi/server/Roboto.ttf differ
Binary files /dev/null and b/src/main/resources/com/stream_pi/server/app_icon.png differ
--- /dev/null
+++ b/src/main/resources/com/stream_pi/server/style.css
@@ -0,0 +1,199 @@
+.root {
+ -fx-font-family : 'Roboto';
+}
+
+.settings_about_streampi_header
+{
+ -fx-font-size : 25;
+}
+
+.settings_about_donate_hyperlink
+{
+ -fx-font-size : 19;
+ -fx-font-weight : bold;
+}
+
+.settings_about_license_label
+{
+ -fx-font-size : 16;
+}
+
+.settings_plugins_each_action, .settings_themes_each_theme, .settings_clients_each_client
+{
+ -fx-border-width : 0 0 1 0;
+ -fx-border-color : grey;
+}
+
+.settings_plugins_each_action_heading, .settings_themes_each_theme_heading, .settings_client_nick_name_label
+{
+ -fx-font-size : 19;
+}
+
+.action_box
+{
+ -fx-border-width: 1px;
+ -fx-shape: "M100,100 h200 a20,20 0 0 1 20,20 v200 a20,20 0 0 1 -20,20 h-200 a20,20 0 0 1 -20,-20 v-200 a20,20 0 0 1 20,-20 z";
+}
+
+.action_box_icon_present
+{
+
+}
+
+.action_box_icon_not_present
+{
+
+}
+
+.action_box_valid
+{
+ -fx-border-color: grey;
+}
+
+.action_box_invalid
+{
+ -fx-border-color: red;
+}
+
+.action_box_display_text_label
+{
+ -fx-font-size : 16;
+ -fx-background-color : transparent;
+}
+
+.action_details_pane_action_heading_label
+{
+ -fx-font-size : 16;
+}
+
+.settings_client_socket_connection_label
+{
+ -fx-font-size : 16;
+}
+
+
+.alert_header
+{
+ -fx-padding: 5;
+}
+
+.alert_pane
+{
+ -fx-background-color : white;
+ -fx-border-color : white;
+ -fx-border-width : 5;
+ -fx-border-radius : 5;
+ -fx-background-radius : 5;
+ -fx-max-width : 400;
+ -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 5, 0.0 , 0.0 , 0 );
+}
+
+.alert_header_icon
+{
+ -fx-icon-size : 30;
+}
+
+.alert_error_icon
+{
+ -fx-icon-color: RED;
+}
+
+.alert_information_icon
+{
+ -fx-icon-color: BLUE;
+}
+
+.alert_warning_icon
+{
+ -fx-icon-color: #ffcc00;
+}
+
+.alert_content_pane
+{
+ -fx-background-color: white;
+ -fx-padding: 5;
+}
+
+.alert_pane_parent, .combobox_pane_parent
+{
+ -fx-background-color : rgba(0,0,0,0.5);
+}
+
+.alert_pane_header_text
+{
+ -fx-font-size: 18;
+}
+
+.alert_button_bar
+{
+ -fx-background-color: white;
+ -fx-alignment: CENTER_RIGHT;
+ -fx-spacing: 5;
+ -fx-padding: 5;
+}
+
+.alert_scroll_pane {
+ -fx-background: #FFFFFF;
+ -fx-border-color:#FFFFFF;
+ -fx-max-height : 300;
+ /*-fx-focus-color: #FFFFFF;
+ -fx-faint-focus-color:#FFFFFF;*/
+}
+
+.dashboard_plugins_pane_action_icon_imageview
+{
+ -fx-width:20;
+ -fx-height:20;
+}
+
+.donate_request_popup_patreon_link
+{
+ -fx-padding : 10 0 0 0;
+ -fx-font-size : 15;
+}
+
+
+.first_time_use_pane
+{
+ -fx-padding : 5;
+}
+
+.first_time_use_pane_heading_label
+{
+ -fx-font-size: 20;
+}
+
+.first_time_use_pane_stackpane
+{
+
+}
+
+.first_time_use_pane_welcome
+{
+
+}
+
+.first_time_use_pane_license
+{
+ -fx-spacing : 10;
+}
+
+.first_time_use_pane_final_config
+{
+
+}
+
+.first_time_use_pane_final_config_label
+{
+ -fx-padding: 0 0 30 0;
+}
+
+.first_time_use_welcome_pane_welcome_label
+{
+ -fx-font-size: 30;
+}
+
+.first_time_use_welcome_pane_next_to_continue_label
+{
+ -fx-font-size: 15;
+}
\ No newline at end of file