diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..211b2857 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index ac30167e..d0b30806 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,7 @@ *.bak *.swp *~.nib - +*.idea # Created by https://www.toptal.com/developers/gitignore/api/eclipse,java # Edit at https://www.toptal.com/developers/gitignore?templates=eclipse,java @@ -114,4 +114,7 @@ hs_err_pid* # End of https://www.toptal.com/developers/gitignore/api/eclipse,java -logs/ \ No newline at end of file +logs/ + +/*/.idea +sources/distro diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..0e14d8e2 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.configuration.updateBuildConfiguration": "disabled" +} \ No newline at end of file diff --git a/sources/.DS_Store b/sources/.DS_Store new file mode 100644 index 00000000..23966e59 Binary files /dev/null and b/sources/.DS_Store differ diff --git a/sources/.project b/sources/.project index 1638d75b..da373099 100644 --- a/sources/.project +++ b/sources/.project @@ -14,4 +14,15 @@ org.eclipse.m2e.core.maven2Nature + + + 1649954610011 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/sources/.vscode/settings.json b/sources/.vscode/settings.json new file mode 100644 index 00000000..e0f15db2 --- /dev/null +++ b/sources/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.configuration.updateBuildConfiguration": "automatic" +} \ No newline at end of file diff --git a/sources/codemetropolis.iml b/sources/codemetropolis.iml new file mode 100644 index 00000000..58c4ad0b --- /dev/null +++ b/sources/codemetropolis.iml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/commons/.project b/sources/commons/.project index 1c053230..1088b79f 100644 --- a/sources/commons/.project +++ b/sources/commons/.project @@ -20,4 +20,15 @@ org.eclipse.jdt.core.javanature org.eclipse.m2e.core.maven2Nature + + + 1649954610016 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/sources/commons/commons.iml b/sources/commons/commons.iml new file mode 100644 index 00000000..a3ee9a94 --- /dev/null +++ b/sources/commons/commons.iml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/commons/src/main/resources/resources.properties b/sources/commons/src/main/resources/resources.properties index 83de1655..10e181f7 100644 --- a/sources/commons/src/main/resources/resources.properties +++ b/sources/commons/src/main/resources/resources.properties @@ -7,7 +7,9 @@ rendering_prefix = Rendering: # Converter info converter_introduction = CodeMetropolis CDF Converter (c) University of Szeged, Department of Software Engineering -converter_usage = Usage: java -jar converter.jar -t -s [-o ] [-p ] +# The tool provides a usage help with a list of proper command line parameters and their valid values to be used: -i, -t, -o, and -p. +# overwrote [-s] to [-i] and to +converter_usage = Usage: java -jar converter.jar -t -i [-o ] [-p ] # Converter notifications converting_to_cdf = Converting input to CDF format... diff --git a/sources/gui/.project b/sources/gui/.project index a7ab247e..59a3bedf 100644 --- a/sources/gui/.project +++ b/sources/gui/.project @@ -20,4 +20,15 @@ org.eclipse.jdt.core.javanature org.eclipse.m2e.core.maven2Nature + + + 1649954610029 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/sources/gui/gui.iml b/sources/gui/gui.iml new file mode 100644 index 00000000..9c381c04 --- /dev/null +++ b/sources/gui/gui.iml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/gui/pom.xml b/sources/gui/pom.xml index ec209eac..17350dd4 100644 --- a/sources/gui/pom.xml +++ b/sources/gui/pom.xml @@ -1,8 +1,5 @@ - + 4.0.0 @@ -61,4 +58,4 @@ ${project.version} - + \ No newline at end of file diff --git a/sources/gui/src/main/java/codemetropolis/toolchain/gui/CodeMetropolisGUI.java b/sources/gui/src/main/java/codemetropolis/toolchain/gui/CodeMetropolisGUI.java index 7ef2ae8a..30506b73 100644 --- a/sources/gui/src/main/java/codemetropolis/toolchain/gui/CodeMetropolisGUI.java +++ b/sources/gui/src/main/java/codemetropolis/toolchain/gui/CodeMetropolisGUI.java @@ -7,32 +7,47 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; import java.io.PipedOutputStream; -import java.util.Random; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTabbedPane; import javax.swing.SwingConstants; import javax.swing.filechooser.FileFilter; +import javax.swing.border.Border; import codemetropolis.toolchain.gui.beans.ExecutionOptions; -import codemetropolis.toolchain.gui.components.CMButton; -import codemetropolis.toolchain.gui.components.CMCheckBox; -import codemetropolis.toolchain.gui.components.CMComboBox; -import codemetropolis.toolchain.gui.components.CMLabel; -import codemetropolis.toolchain.gui.components.CMMetricPanel; -import codemetropolis.toolchain.gui.components.CMSpinner; -import codemetropolis.toolchain.gui.components.CMTextField; +import codemetropolis.toolchain.gui.components.*; import codemetropolis.toolchain.gui.components.listeners.BrowseListener; import codemetropolis.toolchain.gui.utils.ExecutionWorker; import codemetropolis.toolchain.gui.utils.GuiUtils; import codemetropolis.toolchain.gui.utils.Translations; import codemetropolis.toolchain.gui.utils.XmlFileFilter; import codemetropolis.toolchain.placing.layout.LayoutAlgorithm; +import org.apache.commons.lang3.StringUtils; + +import javax.swing.*; +import javax.swing.filechooser.FileFilter; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStreamReader; +import java.io.PipedOutputStream; +import java.net.URL; +import java.util.Random; +import java.util.List; /** * GUI window for the CodeMetropolis toolchain. @@ -78,13 +93,16 @@ public CodeMetropolisGUI(GUIController controller) { addStartButton(panel); initFields(); - + versionUpdateWarning(); this.setResizable(false); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setContentPane(panel); this.pack(); this.setLocationRelativeTo(null); } + public CodeMetropolisGUI(){ + super(Translations.t("gui_title")); + } /** * Does automatic initialization for some of the fields. Search for Minecraft folder if exists. @@ -97,6 +115,123 @@ public void initFields() { } /** + * Gets the latest version from GitHub,via Web Scraping + * GitHub Releases/latest will give back the latest realease. + */ + public String getNewestVersion(String url) { + try { + final URL latestURL = new URL(url); + StringBuilder newestVersion = new StringBuilder(); + BufferedReader urlReader = new BufferedReader(new InputStreamReader(latestURL.openStream())); + String inputLine; + while ((inputLine = urlReader.readLine()) != null) { + if (inputLine.contains("CodeMetropolis/releases/tag/")) { + for (int i = inputLine.indexOf("tag/") + 4; i > 0; i++) { + if (Character.isDigit(inputLine.charAt(i)) || inputLine.charAt(i) == '.') { + newestVersion.append(inputLine.charAt(i)); + } + else{ + break; + } + } + break; + } + } + urlReader.close(); + return newestVersion.toString(); + } catch (Exception e) { + return null; + } + } + + /** + * Gets the actual version from the pom.xml file and filters it to only contains numbers and dots. + */ + public String getActualVersion() { + String version = this.getClass().getPackage().getImplementationVersion(); + StringBuilder fixVersion = new StringBuilder(); + if(version == null){ + return "1.4.0"; + } + for (int i = 0; i < version.length(); i++) { + if (Character.isDigit(version.charAt(i)) || version.charAt(i) == '.') { + fixVersion.append(version.charAt(i)); + } + else{ + break; + } + } + return checkDot(fixVersion.toString()); + } + + /** + * Validates the version string with regular expressions. + * + * @param version a CodeMetropolis version. + */ + public boolean validator(String version) { + return version.matches("[0-9]+(\\.[0-9]+){0,2}"); + } + + /** + * Compares the new and the old version. + * + * @return a true statement if our version is outdated. + */ + public boolean compareVersion(String actualVersionSub, String newVersionSub) { + + if (newVersionSub == null || actualVersionSub == null) { + return false; + } + + if (!validator(actualVersionSub) && !validator(newVersionSub)) { + return false; + } + + String[] actual = actualVersionSub.split("\\."); + String[] newVersion = newVersionSub.split("\\."); + + for (int i = 0; i < newVersionSub.length(); i++) { + try { + if (Integer.parseInt(newVersion[i]) > Integer.parseInt(actual[i])) { + return true; + } else if (Integer.parseInt(newVersion[i]) < Integer.parseInt(actual[i])) { + return false; + } + } catch (Exception e) { + return false; + } + } + return false; + } + + /** + * Checks the amount of dot in the version string. + * If it's less than 2,we are appending a zero to the end. + * + * @param version the checkable version. + */ + public String checkDot(String version) { + int counter = StringUtils.countMatches(version, '.'); + if (counter < 2) { + version += ".0"; + } + return version; + } + + /** + * Checks if we have to notify our user to update the version of CodeMetropolis. + */ + public void versionUpdateWarning() { + if (compareVersion(getActualVersion(),checkDot(getNewestVersion("https://github.com/codemetropolis/CodeMetropolis/releases/latest")))) { + JOptionPane.showMessageDialog(null, "You are using an old version of Codemetropolis\n" + + "Download the latest release from the link below: \n" + + "https://github.com/codemetropolis/CodeMetropolis/releases/latest", "New release available to download", JOptionPane.INFORMATION_MESSAGE); + } + } + + + /** * Creates the base panel for the CodeMetropolis GUI. * * @return The generated {@link JPanel}. @@ -187,132 +322,311 @@ private final void addMetricTabs(JPanel panel) { metricTabbedPane.add(metricPanel.getTabTitle(), metricPanel); } - metricTabbedPane.setBounds(15, 365, 472, 180); - metricTabbedPane.setFont(new Font("Source Sans Pro", Font.PLAIN, 16)); - panel.add(metricTabbedPane); - } + /** + * Does automatic initialization for some of the fields. Search for Minecraft folder if exists. + */ + public void initFields() { + String minecraftRoot = GuiUtils.findMinecraftRoot(); + if (minecraftRoot != null) { + mcRootPath.setText(minecraftRoot); + } + } - /** - * Adds the options for the mapping tool to the {@code panel}. - * - * @param panel The {@link JPanel} to add the components to. - */ - private final void addMappingOptions(JPanel panel) { - CMLabel mappingLabel = new CMLabel(Translations.t("gui_l_mapping"), 15, 555, 120, 30); - mappingPath = new CMTextField(145, 555, 235, 30); - CMButton mappingBrowse = new CMButton(Translations.t("gui_b_browse"), 385, 555, 100, 30); - mappingBrowse.addActionListener(new BrowseListener(mappingPath, JFileChooser.FILES_ONLY, XML_FILTER)); - - CMLabel scaleLabel = new CMLabel(Translations.t("gui_l_scale"), 15, 590, 120, 30); - scaleSpinner = new CMSpinner(145, 590, 120, 30); - - validateStructure = new CMCheckBox(275, 590, 20, 30); - CMLabel validateStructureLabel = new CMLabel(Translations.t("gui_l_validate_structure"), 300, 590, 185, 30); - - panel.add(mappingLabel); - panel.add(mappingPath); - panel.add(mappingBrowse); - panel.add(scaleLabel); - panel.add(scaleSpinner); - panel.add(validateStructure); - panel.add(validateStructureLabel); - } + /** + * Creates the base panel for the CodeMetropolis GUI. + * + * @return The generated {@link JPanel}. + */ + private static final JPanel createBasePanel() { + JPanel panel = new JPanel(); + panel.setLayout(null); + panel.setBackground(Color.WHITE); + panel.setBounds(0, 0, 500, 700); + + Dimension size = new Dimension(500, 750); + panel.setMinimumSize(size); + panel.setPreferredSize(size); + panel.setMaximumSize(size); + + return panel; + } - /** - * Adds the options for the placing tool to the {@code panel}. - * - * @param panel The {@link JPanel} to add the components to. - */ - private final void addPlacingOptions(JPanel panel) { - CMLabel layoutLabel = new CMLabel(Translations.t("gui_l_layout"), 15, 625, 120, 30); - layoutSelector = new CMComboBox(LayoutAlgorithm.values()); - layoutSelector.setBounds(145, 625, 120, 30); - - showMap = new CMCheckBox(275, 625, 20, 30); - CMLabel showMapLabel = new CMLabel(Translations.t("gui_l_show_map"), 300, 625, 185, 30); - - panel.add(layoutLabel); - panel.add(layoutSelector); - panel.add(showMap); - panel.add(showMapLabel); - } + /** + * Adds the cover image and the logo to the top of the {@code panel}. + * + * @param panel The {@link JPanel} to add the components to. + */ + private final void addHeaderImages(JPanel panel) { + JPanel headerPanel = new JPanel(); + headerPanel.setLayout(null); + + // Load the cover and logo images + Image coverImage = new ImageIcon(ClassLoader.getSystemResource("images/cm-background-" + + (rng.nextInt(COVER_IMAGE_COUNT) + 1) + ".png")).getImage().getScaledInstance(500, 200, Image.SCALE_SMOOTH); + ImageIcon logoIcon = new ImageIcon(ClassLoader.getSystemResource("images/cm-logo-border.png")); + Image logoImage = logoIcon.getImage().getScaledInstance(150, 150, Image.SCALE_SMOOTH); + + JLabel coverImageContainer = new JLabel(new ImageIcon(coverImage)); + coverImageContainer.setBounds(0, 0, 500, 200); + JLabel logoImageContainer = new JLabel(new ImageIcon(logoImage)); + logoImageContainer.setBounds(175, 125, 150, 150); + + // Add the icon to the window title bar as well + setIconImage(logoIcon.getImage().getScaledInstance(32, 32, Image.SCALE_SMOOTH)); + + headerPanel.setBackground(Color.WHITE); + headerPanel.setBounds(0, 0, 500, 275); + + headerPanel.add(coverImageContainer); + headerPanel.add(logoImageContainer); + headerPanel.setComponentZOrder(coverImageContainer, 1); + headerPanel.setComponentZOrder(logoImageContainer, 0); + panel.add(headerPanel); + } - /** - * Adds the minecraft root folder browser. This should actually be automatically filled, but in case it is not found - * or the user wishes to save the results to a different location, it enables them to do so. - * - * @param panel The {@link JPanel} to add the components to. - */ - private final void addMinecraftRootBrowser(JPanel panel) { - CMLabel mcRootLabel = new CMLabel(Translations.t("gui_l_mcroot"), 15, 660, 120, 30); - mcRootPath = new CMTextField(145, 660, 235, 30); - CMButton mcRootBrowse = new CMButton(Translations.t("gui_b_browse"), 385, 660, 100, 30); - mcRootBrowse.addActionListener(new BrowseListener(mcRootPath, JFileChooser.DIRECTORIES_ONLY, null)); - - panel.add(mcRootLabel); - panel.add(mcRootPath); - panel.add(mcRootBrowse); - } + /** + * Adds the CodeMetropolis title to the {@code panel} + * + * @param panel The {@link JPanel} to add the components to. + */ + private final void addTitle(JPanel panel) { + JLabel title = new JLabel(Translations.t("gui_title")); + title.setFont(new Font("Source Sans Pro", Font.BOLD, 26)); + title.setHorizontalAlignment(SwingConstants.CENTER); + title.setBounds(0, 280, 500, 30); + + panel.add(title); + } - /** - * Adds the start button to the bottom of panel. - * - * @param panel The {@link JPanel} to add the components to. - */ - private final void addStartButton(JPanel panel) { - CodeMetropolisGUI self = this; - CMButton start = new CMButton(Translations.t("gui_b_generate"), 190, 705, 120, 30); - start.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent event) { - ExecutionOptions executionOptions = controller.getExecutionOptions(); - fillOptions(executionOptions); - if (!fillAndValidateMetricOptions(executionOptions)) { - return; - } + /** + * Adds the project name field to the {@code panel}. + * + * @param panel The {@link JPanel} to add the components to. + */ + private final void addProjectNameField(JPanel panel) { + CMLabel label = new CMLabel(Translations.t("gui_l_project_name"), 15, 325, 120, 30); + projectName = new CMTextField(145, 325, 340, 30); + + panel.add(label); + panel.add(projectName); + } + + /** + * Adds the metric generation tabbed pane to the {@code panel} + * + * @param panel The {@link JPanel} to add the components to. + */ + private final void addMetricTabs(JPanel panel) { + metricTabbedPane = new JTabbedPane(); - if (GuiUtils.validateOptions(controller.getExecutionOptions())) { - PipedOutputStream out = new PipedOutputStream(); - ExecutionDialog dialog = new ExecutionDialog(self, out); - dialog.setVisible(true); - ExecutionWorker worker = new ExecutionWorker(start, controller, out); - worker.execute(); + for (CMMetricPanel metricPanel : controller.getMetricGeneratorPanels()) { + metricTabbedPane.add(metricPanel.getTabTitle(), metricPanel); } + + metricTabbedPane.setBounds(15, 365, 472, 180); + metricTabbedPane.setFont(new Font("Source Sans Pro", Font.PLAIN, 16)); + panel.add(metricTabbedPane); + } + + /** + * Adds the options for the mapping tool to the {@code panel}. + * + * @param panel The {@link JPanel} to add the components to. + */ + private final void addMappingOptions(JPanel panel) { + CMLabel mappingLabel = new CMLabel(Translations.t("gui_l_mapping"), 15, 555, 120, 30); + mappingPath = new CMTextField(145, 555, 235, 30); + CMButton mappingBrowse = new CMButton(Translations.t("gui_b_browse"), 385, 555, 100, 30); + //mappingBrowse.setBorder(new RoundBtn(30)); + mappingBrowse.addActionListener(new BrowseListener(mappingPath, JFileChooser.FILES_ONLY, XML_FILTER)); + + CMLabel scaleLabel = new CMLabel(Translations.t("gui_l_scale"), 15, 590, 120, 30); + scaleSpinner = new CMSpinner(145, 590, 120, 30); + + validateStructure = new CMCheckBox(275, 590, 20, 30); + CMLabel validateStructureLabel = new CMLabel(Translations.t("gui_l_validate_structure"), 300, 590, 185, 30); + + panel.add(mappingLabel); + panel.add(mappingPath); + panel.add(mappingBrowse); + panel.add(scaleLabel); + panel.add(scaleSpinner); + panel.add(validateStructure); + panel.add(validateStructureLabel); + } + + /** + * Adds the options for the placing tool to the {@code panel}. + * + * @param panel The {@link JPanel} to add the components to. + */ + private final void addPlacingOptions(JPanel panel) { + CMLabel layoutLabel = new CMLabel(Translations.t("gui_l_layout"), 15, 625, 120, 30); + layoutSelector = new CMComboBox(LayoutAlgorithm.values()); + layoutSelector.setBounds(145, 625, 120, 30); + + showMap = new CMCheckBox(275, 625, 20, 30); + CMLabel showMapLabel = new CMLabel(Translations.t("gui_l_show_map"), 300, 625, 185, 30); + + panel.add(layoutLabel); + panel.add(layoutSelector); + panel.add(showMap); + panel.add(showMapLabel); + } + + /** + * Adds the minecraft root folder browser. This should actually be automatically filled, but in case it is not found + * or the user wishes to save the results to a different location, it enables them to do so. + * + * @param panel The {@link JPanel} to add the components to. + */ + private final void addMinecraftRootBrowser(JPanel panel) { + CMLabel mcRootLabel = new CMLabel(Translations.t("gui_l_mcroot"), 15, 660, 120, 30); + mcRootPath = new CMTextField(145, 660, 235, 30); + CMButton mcRootBrowse = new CMButton(Translations.t("gui_b_browse"), 385, 660, 100, 30); + mcRootBrowse.addActionListener(new BrowseListener(mcRootPath, JFileChooser.DIRECTORIES_ONLY, null)); + + panel.add(mcRootLabel); + panel.add(mcRootPath); + panel.add(mcRootBrowse); + } + + /** + * Adds the start button to the bottom of panel. + * + * @param panel The {@link JPanel} to add the components to. + */ + private final void addStartButton(JPanel panel) { + CodeMetropolisGUI self = this; + CMButton start = new CMButton(Translations.t("gui_b_generate"), 190, 705, 120, 30); + start.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent event) { + ExecutionOptions executionOptions = controller.getExecutionOptions(); + fillOptions(executionOptions); + /* HTML-like field validation added + Check for emptiness + */ + if(projectName.getText().isEmpty()) { + JOptionPane.showMessageDialog(null, "Please enter project name!"); + return; + }else if(mappingPath.getText().isEmpty()) { + JOptionPane.showMessageDialog(null, "Please select mapping file!"); + return; + }else if(scaleSpinner.getValue()==null) { + JOptionPane.showMessageDialog(null, "Please select scale!"); + return; + }else if(mcRootPath.getText().isEmpty()) { + JOptionPane.showMessageDialog(null, "Please set the Minecraft root path!"); + return; + } + if (!fillAndValidateMetricOptions(executionOptions)) { + return; + } + + + if (GuiUtils.validateOptions(controller.getExecutionOptions())) { + PipedOutputStream out = new PipedOutputStream(); + ExecutionDialog dialog = new ExecutionDialog(self, out); + dialog.setVisible(true); + ExecutionWorker worker = new ExecutionWorker(start, controller, out); + worker.execute(); + } + } + }); + panel.add(start); + } + + /** + * Fills the data required for the metric generation tools. + * + * @param executionOptions The target {@link ExecutionOptions} instance. + * @return True if the options are valid, false otherwise. + */ + private final boolean fillAndValidateMetricOptions(ExecutionOptions executionOptions) { + executionOptions.getMetricGenerationParams().clear(); + + CMMetricPanel currentTab = (CMMetricPanel) metricTabbedPane.getSelectedComponent(); + currentTab.fillFields(executionOptions); + return currentTab.validateFields(executionOptions); + } + + /** + * Fills the data from the UI fields to the given {@link ExecutionOptions} instance. + * + * @param executionOptions The target instance. + */ + private final void fillOptions(ExecutionOptions executionOptions) { + Double scale = (Double) scaleSpinner.getValue(); + executionOptions.setProjectName(projectName.getText()); + executionOptions.setMappingXml(new File(mappingPath.getText())); + executionOptions.setScale(scale.floatValue()); + executionOptions.setValidate(validateStructure.isSelected()); + executionOptions.setLayoutAlgorithm((LayoutAlgorithm) layoutSelector.getSelectedItem()); + executionOptions.setShowMap(showMap.isSelected()); + executionOptions.setMinecraftRoot(new File(mcRootPath.getText())); + } + + private final void readProTipsJSON() { + protips = new ArrayList<>(); + + try { + File myObj = new File("..\\gui\\src\\main\\resources\\protips.json"); + + Scanner myReader = new Scanner(myObj); + StringBuilder data = new StringBuilder(); + + while (myReader.hasNextLine()) { + data.append(myReader.nextLine()); } - }); - panel.add(start); + Matcher m = Pattern.compile("\".+?\"").matcher(data.toString()); + while (m.find()) { + protips.add(m.group()); + } + + protips.remove(0); + + myReader.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } } /** - * Fills the data required for the metric generation tools. + * Adds the lightbulb image next to the pro tip. * - * @param executionOptions The target {@link ExecutionOptions} instance. - * @return True if the options are valid, false otherwise. + * @param panel The {@link JPanel} to add the components to. */ - private final boolean fillAndValidateMetricOptions(ExecutionOptions executionOptions) { - executionOptions.getMetricGenerationParams().clear(); + private final void addProTipImage(JPanel panel) { + // Load the cover and logo images + ImageIcon bulbIcon = new ImageIcon(ClassLoader.getSystemResource("images/cm-lightbulb.png")); + Image bulbLogo = bulbIcon.getImage().getScaledInstance(30, 30, Image.SCALE_SMOOTH); - CMMetricPanel currentTab = (CMMetricPanel) metricTabbedPane.getSelectedComponent(); - currentTab.fillFields(executionOptions); - return currentTab.validateFields(executionOptions); + JLabel logoImageContainer = new JLabel(new ImageIcon(bulbLogo)); + logoImageContainer.setBounds(60, 290, 30, 30); + + panel.add(logoImageContainer); } /** - * Fills the data from the UI fields to the given {@link ExecutionOptions} instance. + * Adds a random pro tip to the {@code panel} * - * @param executionOptions The target instance. + * @param panel The {@link JPanel} to add the components to. */ - private final void fillOptions(ExecutionOptions executionOptions) { - Double scale = (Double) scaleSpinner.getValue(); - executionOptions.setProjectName(projectName.getText()); - executionOptions.setMappingXml(new File(mappingPath.getText())); - executionOptions.setScale(scale.floatValue()); - executionOptions.setValidate(validateStructure.isSelected()); - executionOptions.setLayoutAlgorithm((LayoutAlgorithm) layoutSelector.getSelectedItem()); - executionOptions.setShowMap(showMap.isSelected()); - executionOptions.setMinecraftRoot(new File(mcRootPath.getText())); + private final void addProTip(JPanel panel) { + readProTipsJSON(); + + JLabel tip = new JLabel(protips.get(rng.nextInt(protips.size()))); + tip.setFont(new Font("Source Sans Pro", Font.BOLD, 10)); + tip.setHorizontalAlignment(SwingConstants.CENTER); + tip.setBounds(100, 300, 300, 20); + tip.setOpaque(true); + tip.setBackground(Color.orange); + + panel.add(tip); } } + diff --git a/sources/gui/src/main/java/codemetropolis/toolchain/gui/Main.java b/sources/gui/src/main/java/codemetropolis/toolchain/gui/Main.java index 37470cf3..c1cb2cbb 100644 --- a/sources/gui/src/main/java/codemetropolis/toolchain/gui/Main.java +++ b/sources/gui/src/main/java/codemetropolis/toolchain/gui/Main.java @@ -1,13 +1,17 @@ package codemetropolis.toolchain.gui; +import java.awt.Component; import java.awt.Font; import java.awt.FontFormatException; +import java.awt.Graphics; import java.awt.GraphicsEnvironment; +import java.awt.Insets; import java.io.IOException; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; + /** * Main class for the CodeMetropolis' GUI module. Initializes some globals, like fonts and look-and-feel, and * instaniates the main gui window. @@ -62,3 +66,7 @@ private static final void loadSourceSansProFonts() { } } + + + + diff --git a/sources/gui/src/main/java/codemetropolis/toolchain/gui/components/CMButton.java b/sources/gui/src/main/java/codemetropolis/toolchain/gui/components/CMButton.java index 8aa2d5da..04674836 100644 --- a/sources/gui/src/main/java/codemetropolis/toolchain/gui/components/CMButton.java +++ b/sources/gui/src/main/java/codemetropolis/toolchain/gui/components/CMButton.java @@ -1,6 +1,15 @@ package codemetropolis.toolchain.gui.components; +import java.awt.Color; +import java.awt.Dimension; import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.geom.Ellipse2D; import javax.swing.JButton; @@ -11,34 +20,81 @@ */ public class CMButton extends JButton { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private static final Font BUTTON_FONT = new Font("Source Sans Pro", Font.PLAIN, 16); + private static final Font BUTTON_FONT = new Font("Source Sans Pro", Font.PLAIN, 12); - /** - * Constructs a {@link CMButton} instance. - * - * @param label The label for this button. - */ - public CMButton(String label) { - super(label); - setFont(BUTTON_FONT); - } + /** + * Constructs a {@link CMButton} instance. + * + * @param label The label for this button. + */ + public CMButton(String label) { + super(label); + setFont(BUTTON_FONT); + + /* get the element size and set the element size */ + Dimension size = getPreferredSize(); + size.width = size.height = Math.max(size.width, size.height); + setPreferredSize(size); - /** - * Constructs a {@link CMButton} instance, and sets its position and size. - * - * @param label The label for this button. - * @param x The x position on the ui. - * @param y The y position on the ui. - * @param width The width of the element. - * @param height The height of the element. - */ - public CMButton(String label, int x, int y, int width, int height) { - this(label); + setContentAreaFilled(false); - setBounds(x, y, width, height); - } + } + + + /** + * @param g The graphics parameter of object + * This method is drawing background color for the button. + * The super call represents the normal paintComponent method. + * @author Tarkó Máté (h985712) + */ + + @Override + protected void paintComponent(Graphics g) { + if(getModel().isArmed()){ + g.setColor(new Color(255,255,0)); + setForeground(getForeground()); + }else{ + g.setColor(new Color(0,153,153)); + setForeground(Color.BLACK); + /* If the button is the generate button, we set the background of the button to a distinctive color */ + if(this.getText().equals("Generate")){ + g.setColor(Color.ORANGE); + } + } + g.fillRoundRect(0, 0, getSize().width-1, getSize().height-1, 30, 30); + + super.paintComponent(g); + } + + + /** + * @param g The graphics parameter of object + * This method is drawing border for rounded button. + * @author Tarkó Máté (h985712) + */ + @Override + protected void paintBorder(Graphics g) { + g.setColor(getForeground()); + g.drawRoundRect(0,0,getSize().width-1,getSize().height-1, 30,30); + } + + /** + * Constructs a {@link CMButton} instance, and sets its position and size. + * + * @param label The label for this button. + * @param x The x position on the ui. + * @param y The y position on the ui. + * @param width The width of the element. + * @param height The height of the element. + */ + public CMButton(String label, int x, int y, int width, int height) { + this(label); + + setBounds(x, y, width, height); + } } + diff --git a/sources/gui/src/main/java/codemetropolis/toolchain/gui/components/listeners/BrowseListener.java b/sources/gui/src/main/java/codemetropolis/toolchain/gui/components/listeners/BrowseListener.java index 9e4776d7..49cce755 100644 --- a/sources/gui/src/main/java/codemetropolis/toolchain/gui/components/listeners/BrowseListener.java +++ b/sources/gui/src/main/java/codemetropolis/toolchain/gui/components/listeners/BrowseListener.java @@ -40,6 +40,7 @@ public BrowseListener(CMTextField fileNameTextField, int fileSelectionMode, File public void actionPerformed(ActionEvent event) { if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { fileNameTextField.setText(fileChooser.getSelectedFile().getAbsolutePath()); + fileNameTextField.requestFocus(); } } diff --git a/sources/gui/src/main/java/codemetropolis/toolchain/gui/metricgenerators/SourceMeterGenerator.java b/sources/gui/src/main/java/codemetropolis/toolchain/gui/metricgenerators/SourceMeterGenerator.java index 29501635..31a9c643 100644 --- a/sources/gui/src/main/java/codemetropolis/toolchain/gui/metricgenerators/SourceMeterGenerator.java +++ b/sources/gui/src/main/java/codemetropolis/toolchain/gui/metricgenerators/SourceMeterGenerator.java @@ -1,10 +1,17 @@ package codemetropolis.toolchain.gui.metricgenerators; import java.io.File; +import java.nio.file.Files; +import java.nio.file.InvalidPathException; +import java.nio.file.Paths; import java.util.Map; import javax.swing.JFileChooser; +import javax.swing.JTextField; import javax.swing.filechooser.FileFilter; +import java.awt.Color; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; import codemetropolis.toolchain.converter.control.ConverterType; import codemetropolis.toolchain.gui.beans.ExecutionOptions; @@ -28,6 +35,9 @@ public class SourceMeterGenerator extends CMMetricPanel { private static final FileFilter EXE_FILTER = new ExeFileFilter(); + private static final Color colorGreen = Color.decode(Translations.t("color_green")); + private static final Color colorRed = Color.decode(Translations.t("color_red")); + private CMTextField projectRootPath; private CMTextField sourceMeterPath; @@ -44,12 +54,63 @@ public SourceMeterGenerator() { addSourceMeterExecutableField(); } + public boolean validatePath(String path) { + if (path.isEmpty()) + return false; + try { + return Files.exists(Paths.get(path)); + } catch (InvalidPathException | NullPointerException ex) { + return false; + } + } + + /** + * Function for checking the project root field, if the file is correct, the field turns green, otherwise it turns red. + * + * @return Return with focuslistener. + */ + public FocusListener getFocusListener() { + FocusListener focusListener = new FocusListener() { + public void focusGained(FocusEvent focusEvent) { + try { + JTextField src = (JTextField) focusEvent.getSource(); + if (!src.getText().isEmpty()) { + if (validatePath(src.getText())) { + src.setBackground(colorGreen); + } else { + src.setBackground(colorRed); + } + } + } catch (ClassCastException ignored) { + GuiUtils.showError(Translations.t("gui_err_unexpected_err")); + } + } + + public void focusLost(FocusEvent focusEvent) { + try { + JTextField src = (JTextField) focusEvent.getSource(); + if (validatePath(src.getText())) { + src.setBackground(colorGreen); + } else { + src.setBackground(colorRed); + } + } catch (ClassCastException ignored) { + GuiUtils.showError(Translations.t("gui_err_unexpected_err")); + } + } + }; + return focusListener; + } + /** * Adds the project root browser to the panel. */ public void addProjectRootField() { CMLabel label = new CMLabel(Translations.t("gui_l_project_root"), 5, 5, 120, 30); projectRootPath = new CMTextField(130, 5, 225, 30); + + projectRootPath.addFocusListener(getFocusListener()); + CMButton browseButton = new CMButton(Translations.t("gui_b_browse"), 360, 5, 100, 30); browseButton.addActionListener(new BrowseListener(projectRootPath, JFileChooser.DIRECTORIES_ONLY, null)); diff --git a/sources/gui/src/main/resources/images/cm-lightbulb.png b/sources/gui/src/main/resources/images/cm-lightbulb.png new file mode 100644 index 00000000..ab134d2a Binary files /dev/null and b/sources/gui/src/main/resources/images/cm-lightbulb.png differ diff --git a/sources/gui/src/main/resources/protips.json b/sources/gui/src/main/resources/protips.json new file mode 100644 index 00000000..b262e728 --- /dev/null +++ b/sources/gui/src/main/resources/protips.json @@ -0,0 +1,3 @@ +{"tips": [ + "pro tip1", "pro tip2", "pro tip3" +]} diff --git a/sources/gui/src/main/resources/translations.properties b/sources/gui/src/main/resources/translations.properties index f56865a2..920417bf 100644 --- a/sources/gui/src/main/resources/translations.properties +++ b/sources/gui/src/main/resources/translations.properties @@ -61,3 +61,7 @@ gui_err_sm_run_failed = Failed to run SourceMeter! gui_err_unexpected_err = Unexpected error occured! gui_err_unhandled_metric_source = Unhandled metric source! gui_err_world_gen_failed = World generation failed! Check logs for details! + +#Colors +color_green = 0xA5FFB4 +color_red = 0xFF9C9C diff --git a/sources/gui/src/test/java/codemetropolis/toolchain/gui/utils/CodeMetropolisGUITest.java b/sources/gui/src/test/java/codemetropolis/toolchain/gui/utils/CodeMetropolisGUITest.java new file mode 100644 index 00000000..e2ed704b --- /dev/null +++ b/sources/gui/src/test/java/codemetropolis/toolchain/gui/utils/CodeMetropolisGUITest.java @@ -0,0 +1,64 @@ +package codemetropolis.toolchain.gui.utils; + +import static org.junit.jupiter.api.Assertions.*; + +import codemetropolis.toolchain.gui.CodeMetropolisGUI; +import codemetropolis.toolchain.gui.GUIController; +import org.junit.jupiter.api.Test; + +public class CodeMetropolisGUITest { + + CodeMetropolisGUI codeMetropolisGUI = new CodeMetropolisGUI(); + @Test + public void testGetNewestVersion(){ + assertEquals("1.4",codeMetropolisGUI.getNewestVersion("https://github.com/codemetropolis/CodeMetropolis/releases/latest")); + assertEquals("1.4",codeMetropolisGUI.getNewestVersion("https://github.com/codemetropolis/CodeMetropolis/releases/tag/1.4")); + assertEquals("1.3",codeMetropolisGUI.getNewestVersion("https://github.com/codemetropolis/CodeMetropolis/releases/tag/1.3")); + assertEquals("1.3.2",codeMetropolisGUI.getNewestVersion("https://github.com/codemetropolis/CodeMetropolis/releases/tag/1.3.2-alpha")); + assertEquals("1.3.1",codeMetropolisGUI.getNewestVersion("https://github.com/codemetropolis/CodeMetropolis/releases/tag/1.3.1-alpha")); + } + + @Test + public void testCheckDot(){ + assertEquals("1.4.0",codeMetropolisGUI.checkDot("1.4")); + assertEquals("1.4.0",codeMetropolisGUI.checkDot("1.4.0")); + assertEquals("1.4.",codeMetropolisGUI.checkDot("1.4.")); + assertEquals("14.0",codeMetropolisGUI.checkDot("14")); + assertEquals(".14.0",codeMetropolisGUI.checkDot(".14")); + assertEquals("..0",codeMetropolisGUI.checkDot(".")); + assertEquals("..",codeMetropolisGUI.checkDot("..")); + assertEquals(".0",codeMetropolisGUI.checkDot("")); + } + + @Test + public void testValidator(){ + assertTrue(codeMetropolisGUI.validator("1.4.2")); + assertTrue(codeMetropolisGUI.validator("12222.1251")); + assertTrue(codeMetropolisGUI.validator("1")); + assertFalse(codeMetropolisGUI.validator("")); + assertFalse(codeMetropolisGUI.validator("1.")); + assertFalse(codeMetropolisGUI.validator(".1")); + assertFalse(codeMetropolisGUI.validator(".")); + assertFalse(codeMetropolisGUI.validator("1.34.d3")); + assertFalse(codeMetropolisGUI.validator("xxx")); + assertFalse(codeMetropolisGUI.validator("1.4.5.0")); + } + + @Test + public void testCompareVersion(){ + assertTrue(codeMetropolisGUI.compareVersion("1", "2")); + assertTrue(codeMetropolisGUI.compareVersion("1.0", "1.1")); + assertTrue(codeMetropolisGUI.compareVersion("1.0.0", "1.0.1")); + assertTrue(codeMetropolisGUI.compareVersion("0.0.2", "0.0.4")); + assertFalse(codeMetropolisGUI.compareVersion("1.4.2", "1.4.2")); + assertFalse(codeMetropolisGUI.compareVersion("1.4.2", "0.0.0")); + assertFalse(codeMetropolisGUI.compareVersion("1", "0")); + assertFalse(codeMetropolisGUI.compareVersion("1.1", "1.0")); + assertFalse(codeMetropolisGUI.compareVersion("1.1.4", "1.1.3")); + assertFalse(codeMetropolisGUI.compareVersion("1.", "1.")); + assertFalse(codeMetropolisGUI.compareVersion("1", "")); + assertFalse(codeMetropolisGUI.compareVersion(".1", ".1.")); + assertFalse(codeMetropolisGUI.compareVersion("XXX", "1A.B")); + assertFalse(codeMetropolisGUI.compareVersion("", "")); + } +} diff --git a/sources/gui/src/test/java/codemetropolis/toolchain/mapping/MappingExecutorTest.java b/sources/gui/src/test/java/codemetropolis/toolchain/mapping/MappingExecutorTest.java new file mode 100644 index 00000000..11172ef0 --- /dev/null +++ b/sources/gui/src/test/java/codemetropolis/toolchain/mapping/MappingExecutorTest.java @@ -0,0 +1,33 @@ +package codemetropolis.toolchain.mapping; + +import codemetropolis.toolchain.commons.util.Resources; +import codemetropolis.toolchain.mapping.model.Mapping; +import org.junit.jupiter.api.Test; +import org.junit.runners.Parameterized; + +import static codemetropolis.toolchain.mapping.MappingExecutor.MAX_SCALE; +import static codemetropolis.toolchain.mapping.MappingExecutor.MIN_SCALE; +import static org.junit.jupiter.api.Assertions.*; + +class MappingExecutorTest { + + /** + * testing if required resources exist. + */ + + @Test + void execute() { + + assertNotNull(Resources.get("reading_mapping")); + assertNotNull(Resources.get("reading_mapping_done")); + assertNotNull(Resources.get("reading_graph")); + assertNotNull(Resources.get("reading_graph_done")); + assertNotNull(Resources.get("linking_metrics")); + assertNotNull(Resources.get("linking_metrics_done")); + assertNotNull(Resources.get("invalid_hierarchy_error")); + assertNotNull(Resources.get("mapping_printing_output")); + assertNotNull(Resources.get("cmxml_writer_error")); + assertNotNull(Resources.get("mapping_printing_output_done")); + + } +} \ No newline at end of file diff --git a/sources/integration/.project b/sources/integration/.project index 00635b5a..875f7dfc 100644 --- a/sources/integration/.project +++ b/sources/integration/.project @@ -14,4 +14,15 @@ org.eclipse.m2e.core.maven2Nature + + + 1649954610039 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/sources/integration/integration.iml b/sources/integration/integration.iml new file mode 100644 index 00000000..58c4ad0b --- /dev/null +++ b/sources/integration/integration.iml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/integration/spigot-plugin/.project b/sources/integration/spigot-plugin/.project index 6f344b97..9734663c 100644 --- a/sources/integration/spigot-plugin/.project +++ b/sources/integration/spigot-plugin/.project @@ -20,4 +20,15 @@ org.eclipse.m2e.core.maven2Nature org.eclipse.jdt.core.javanature + + + 1649954610058 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/sources/integration/spigot-plugin/spigot-plugin.iml b/sources/integration/spigot-plugin/spigot-plugin.iml new file mode 100644 index 00000000..fec4a260 --- /dev/null +++ b/sources/integration/spigot-plugin/spigot-plugin.iml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/pom.xml b/sources/pom.xml index 022749a7..27f4d52a 100644 --- a/sources/pom.xml +++ b/sources/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 codemetropolis @@ -67,10 +67,10 @@ test - - - - + + + + org.apache.maven.plugins maven-jar-plugin @@ -80,6 +80,8 @@ true lib/ + true + true . @@ -87,8 +89,8 @@ - - org.apache.maven.plugins + + org.apache.maven.plugins maven-dependency-plugin 3.2.0 @@ -121,35 +123,35 @@ - - - - - - - maven-resources-plugin - 3.2.0 - - - copy-resources - package - - copy-resources - - - ${session.executionRootDirectory}/distro - - - ${project.build.directory} - - *.jar - - - - - - - - - + + + + + + + maven-resources-plugin + 3.2.0 + + + copy-resources + package + + copy-resources + + + ${session.executionRootDirectory}/distro + + + ${project.build.directory} + + *.jar + + + + + + + + + \ No newline at end of file diff --git a/sources/toolchain/.project b/sources/toolchain/.project index 1638d75b..b9f8b88b 100644 --- a/sources/toolchain/.project +++ b/sources/toolchain/.project @@ -14,4 +14,15 @@ org.eclipse.m2e.core.maven2Nature + + + 1649954610063 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/sources/toolchain/converter/.project b/sources/toolchain/converter/.project index 6d3ab881..7b65f5a6 100644 --- a/sources/toolchain/converter/.project +++ b/sources/toolchain/converter/.project @@ -20,4 +20,15 @@ org.eclipse.jdt.core.javanature org.eclipse.m2e.core.maven2Nature + + + 1649954610023 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/sources/toolchain/converter/converter.iml b/sources/toolchain/converter/converter.iml new file mode 100644 index 00000000..9811acb5 --- /dev/null +++ b/sources/toolchain/converter/converter.iml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/toolchain/converter/src/main/java/codemetropolis/toolchain/converter/CommandLineOptions.java b/sources/toolchain/converter/src/main/java/codemetropolis/toolchain/converter/CommandLineOptions.java index 39848d5e..d2c9281d 100644 --- a/sources/toolchain/converter/src/main/java/codemetropolis/toolchain/converter/CommandLineOptions.java +++ b/sources/toolchain/converter/src/main/java/codemetropolis/toolchain/converter/CommandLineOptions.java @@ -10,8 +10,11 @@ public class CommandLineOptions { @Option(name="-t", aliases = {"--type"}) private String type = null; - - @Option(name="-s", aliases = { "--source", "-i", "--input" }) + + /** + * Option [-i], input, the path of the input graph file. Required + */ + @Option(name="-i", aliases = { "--input" })//overwrote [-s] to [-i], delete "--source, -s" private String source = null; @Option(name="-o", aliases = {"--output"}) diff --git a/sources/toolchain/mapping/.project b/sources/toolchain/mapping/.project index 2bd1712a..6b631e3a 100644 --- a/sources/toolchain/mapping/.project +++ b/sources/toolchain/mapping/.project @@ -20,4 +20,15 @@ org.eclipse.jdt.core.javanature org.eclipse.m2e.core.maven2Nature + + + 1649954610043 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/sources/toolchain/mapping/mapping.iml b/sources/toolchain/mapping/mapping.iml new file mode 100644 index 00000000..0752ffa2 --- /dev/null +++ b/sources/toolchain/mapping/mapping.iml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/toolchain/mapping/pom.xml b/sources/toolchain/mapping/pom.xml index 758e298c..46d11179 100644 --- a/sources/toolchain/mapping/pom.xml +++ b/sources/toolchain/mapping/pom.xml @@ -56,5 +56,17 @@ jaxb-api 2.1 + + org.testng + testng + RELEASE + compile + + + junit + junit + 4.12 + compile + diff --git a/sources/toolchain/mapping/src/main/java/codemetropolis/toolchain/mapping/MappingExecutor.java b/sources/toolchain/mapping/src/main/java/codemetropolis/toolchain/mapping/MappingExecutor.java index 2df108a3..b57cdeef 100644 --- a/sources/toolchain/mapping/src/main/java/codemetropolis/toolchain/mapping/MappingExecutor.java +++ b/sources/toolchain/mapping/src/main/java/codemetropolis/toolchain/mapping/MappingExecutor.java @@ -19,7 +19,7 @@ public class MappingExecutor extends AbstractExecutor { public static final double MIN_SCALE = 0.01; public static final double MAX_SCALE = 100; - + @Override public boolean execute(ExecutorArgs args) { MappingExecutorArgs mappingArgs = (MappingExecutorArgs)args; @@ -28,7 +28,12 @@ public boolean execute(ExecutorArgs args) { printError(null, Resources.get("invalid_scale_error"), MIN_SCALE, MAX_SCALE); return false; } - + + /** + * try-catch blocks to handle invalid XML inputs. + * @param mapping XML file content + * @param MappingReaderException Invalid XML content + */ print(Resources.get("reading_mapping")); Mapping mapping; try { @@ -36,8 +41,8 @@ public boolean execute(ExecutorArgs args) { } catch (FileNotFoundException e) { printError(e, Resources.get("mapping_not_found_error")); return false; - } catch (MappingReaderException e) { - printError(e, e.getMessage()); + } catch (MappingReaderException e) { //we print a warning, instead of a long error message. + System.out.println("The XML file's content is invalid."); return false; } print(Resources.get("reading_mapping_done")); @@ -85,8 +90,7 @@ public boolean execute(ExecutorArgs args) { return false; } print(Resources.get("mapping_printing_output_done")); - + return true; } - } diff --git a/sources/toolchain/placing/.project b/sources/toolchain/placing/.project index 3f758d7f..e79043f2 100644 --- a/sources/toolchain/placing/.project +++ b/sources/toolchain/placing/.project @@ -20,4 +20,15 @@ org.eclipse.jdt.core.javanature org.eclipse.m2e.core.maven2Nature + + + 1649954610048 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/sources/toolchain/placing/placing.iml b/sources/toolchain/placing/placing.iml new file mode 100644 index 00000000..84f346d7 --- /dev/null +++ b/sources/toolchain/placing/placing.iml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/toolchain/placing/src/main/java/codemetropolis/toolchain/placing/PlacingExecutor.java b/sources/toolchain/placing/src/main/java/codemetropolis/toolchain/placing/PlacingExecutor.java index c6d40ff7..f081a388 100644 --- a/sources/toolchain/placing/src/main/java/codemetropolis/toolchain/placing/PlacingExecutor.java +++ b/sources/toolchain/placing/src/main/java/codemetropolis/toolchain/placing/PlacingExecutor.java @@ -29,8 +29,13 @@ public boolean execute(ExecutorArgs args) { } catch (IOException e) { printError(e, Resources.get("missing_input_xml_error")); return false; + } catch (CmxmlValidationFailedException e) { - printError(e, Resources.get("invalid_input_xml_error")); + /** Warns the user that the input file content is invalid + * and exits normally without creating the output file. + */ + printError(e, "\nmappingToPlacing.xml is invalid," + + " please check the content of the input file or generate new mappingToPlacing.xml."); return false; } @@ -61,7 +66,9 @@ public boolean execute(ExecutorArgs args) { try { buildables.writeToFile(placingArgs.getOutputFile(), "placing", "rendering", "1.0"); } catch (CmxmlWriterException e) { - printError(e, Resources.get("cmxml_writer_error")); + // Warns the user that the output file parameter value is invalid in placing and exits normally without creating the output file. + printError(e, "\nThe output file parameter is invalid!" + + "Please check that the drive exist!"); return false; } print(Resources.get("placing_printing_output_done")); diff --git a/sources/toolchain/rendering/.project b/sources/toolchain/rendering/.project index 50885699..72508208 100644 --- a/sources/toolchain/rendering/.project +++ b/sources/toolchain/rendering/.project @@ -20,4 +20,15 @@ org.eclipse.m2e.core.maven2Nature org.eclipse.jdt.core.javanature + + + 1649954610054 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/sources/toolchain/rendering/rendering.iml b/sources/toolchain/rendering/rendering.iml new file mode 100644 index 00000000..8fe19ebc --- /dev/null +++ b/sources/toolchain/rendering/rendering.iml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/toolchain/rendering/src/main/java/codemetropolis/toolchain/rendering/Main.java b/sources/toolchain/rendering/src/main/java/codemetropolis/toolchain/rendering/Main.java index 2de98730..f274002a 100644 --- a/sources/toolchain/rendering/src/main/java/codemetropolis/toolchain/rendering/Main.java +++ b/sources/toolchain/rendering/src/main/java/codemetropolis/toolchain/rendering/Main.java @@ -12,7 +12,12 @@ public class Main { public static void main(String[] args) { - + int javaVersion = parseJavaVersion(System.getProperty("java.version")); + + if(javaVersion != 8) { // Works with only Java 8 version. + throw new RuntimeException("The required Java version is 8, you have Java " + javaVersion); // Warns the user if the Java version is not 8. + } + FileLogger.load(Settings.get("rendering_log_file")); CommandLineOptions options = new CommandLineOptions(); @@ -79,4 +84,23 @@ private void printProgress(String message, ProgressEvent event) { } + /** + * java.version is a system property that exists in every JVM. + * There are two possible formats for it, because the version format changed after Java 8: + * Java 8 or lower: 1.6.0_12, 1.7.0, 1.7.0_22, 1.8.0_201 + * Java 9 or higher: 9.0.1, 10.1.4, 12, 12.0.1 + * @param version string of version numbers formatted in 'x.y.z' or '1.x.y_z' + * @return parsed version number in integer + */ + private static int parseJavaVersion(String version) { + if(version.startsWith("1.")) { // Under Java 8 and Java 8 version. Parse 1.x.y_z format string. + version = version.substring(2, 3); + + } else { // After Java 8 version. Parse x.y.z format string. + int dot = version.indexOf("."); + if(dot != -1) { + version = version.substring(0, dot); + } + } return Integer.parseInt(version); + } } diff --git a/sources/toolchain/rendering/src/main/java/codemetropolis/toolchain/rendering/model/building/Floor.java b/sources/toolchain/rendering/src/main/java/codemetropolis/toolchain/rendering/model/building/Floor.java index ced4a538..99b5765a 100644 --- a/sources/toolchain/rendering/src/main/java/codemetropolis/toolchain/rendering/model/building/Floor.java +++ b/sources/toolchain/rendering/src/main/java/codemetropolis/toolchain/rendering/model/building/Floor.java @@ -9,6 +9,7 @@ import codemetropolis.toolchain.rendering.model.pattern.RepeationPattern; import codemetropolis.toolchain.rendering.model.primitive.Door; import codemetropolis.toolchain.rendering.model.primitive.EmptyBox; +import codemetropolis.toolchain.rendering.model.primitive.Ladder; import codemetropolis.toolchain.rendering.model.primitive.Row; import codemetropolis.toolchain.rendering.model.primitive.SolidBox; import codemetropolis.toolchain.rendering.model.primitive.WallSign; @@ -28,8 +29,21 @@ public Floor(Buildable innerBuildable) throws BuildingTypeMismatchException { prepareDoor(); prepareSigns(); prepareTorches(); + prepareLadders(); } + /** + * Puts ladders on the four corners of the floor all along the edges. + */ + private void prepareLadders() { + for(int i = 0; i < size.getY(); i++){ + primitives.add(new Ladder(position.getX(), position.getY() + i, position.getZ() - 1, Ladder.Orientation.NORTH)); + primitives.add(new Ladder(position.getX() - 1, position.getY() + i, position.getZ() + size.getZ() - 1, Ladder.Orientation.WEST)); + primitives.add(new Ladder(position.getX() + size.getX() - 1, position.getY() + i, position.getZ() + size.getZ(), Ladder.Orientation.SOUTH)); + primitives.add(new Ladder(position.getX() + size.getX(), position.getY() + i, position.getZ(), Ladder.Orientation.EAST)); + } + } + protected void prepareDoor() { BasicBlock _red = new BasicBlock( "minecraft:redstone_block" ); BasicBlock _lgt = new BasicBlock( "minecraft:lit_redstone_lamp" ); diff --git a/sources/toolchain/rendering/src/main/java/codemetropolis/toolchain/rendering/model/primitive/Ladder.java b/sources/toolchain/rendering/src/main/java/codemetropolis/toolchain/rendering/model/primitive/Ladder.java new file mode 100644 index 00000000..1cf4ffa0 --- /dev/null +++ b/sources/toolchain/rendering/src/main/java/codemetropolis/toolchain/rendering/model/primitive/Ladder.java @@ -0,0 +1,67 @@ +package codemetropolis.toolchain.rendering.model.primitive; + +import java.io.File; + +import codemetropolis.toolchain.commons.cmxml.Point; +import codemetropolis.toolchain.rendering.model.BasicBlock; + +/** + * Represents the ladder object in Minecraft. + */ +public class Ladder implements Primitive{ + + /** + * Defines the direction that the ladder is facing. + */ + public enum Orientation { + NORTH(2), + SOUTH(3), + WEST(4), + EAST(5); + + private final int value; + + Orientation(int v) { + value = v; + } + + public int getValue() { + return value; + } + } + + private Point position; + private Orientation orientation; + + /** + * Creates a new ladder object. + * @param x The coords position of the ladder on the X axis. + * @param y The coords position of the ladder on the Y axis. + * @param z The coords position of the ladder on the Z axis. + * @param orientation The direction that the ladder is facing. + */ + public Ladder(int x, int y, int z, Orientation orientation) { + super(); + this.position = new Point(x, y, z); + this.orientation = orientation; + } + + /** + * Tells how the ladder block would be saved into the final CSV file. + * @return The number of blocks placed. + */ + @Override + public int toCSVFile(File directory) { + new Boxel(new BasicBlock((short) 65, orientation.getValue()), position).toCSVFile(directory); + return getNumberOfBlocks(); + } + + /** + * Tells us a ladder object in Minecraft consist of how many ingame blocks. + */ + @Override + public int getNumberOfBlocks() { + return 1; + } + +} diff --git a/sources/toolchain/toolchain.iml b/sources/toolchain/toolchain.iml new file mode 100644 index 00000000..58c4ad0b --- /dev/null +++ b/sources/toolchain/toolchain.iml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file