From 11c9d19c25f10b717e3c9534c65298bb10d31a53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ozan=20E=C4=9Fitmen?= Date: Sat, 7 Nov 2015 22:01:19 +0300 Subject: [PATCH 1/3] Initial commit, has missing code --- gui/README.md | 6 + gui/src/asl/gui/Main.java | 411 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 417 insertions(+) create mode 100644 gui/README.md create mode 100644 gui/src/asl/gui/Main.java diff --git a/gui/README.md b/gui/README.md new file mode 100644 index 0000000..0eea8ae --- /dev/null +++ b/gui/README.md @@ -0,0 +1,6 @@ +ASL GUI +=========== + +An optional Java interface to make the compile procces of ASL faster and more user-friendly. It's released under the MIT licence just like the core project. + +Maintained by yours truly: [654wak654](https://github.com/654wak654/) \ No newline at end of file diff --git a/gui/src/asl/gui/Main.java b/gui/src/asl/gui/Main.java new file mode 100644 index 0000000..bee0e78 --- /dev/null +++ b/gui/src/asl/gui/Main.java @@ -0,0 +1,411 @@ +/* + * The MIT License + * + * Copyright 2015 Ozan Egitmen. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package asl.gui; + +import java.awt.Color; +import java.io.File; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.prefs.Preferences; +import javax.swing.BorderFactory; +import javax.swing.JFileChooser; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.border.Border; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.plaf.ColorUIResource; + +public class Main extends javax.swing.JFrame { + + Preferences prefs = Preferences.userRoot().node(this.getClass().getName()); + boolean outputFixDir = false; + + public Main() { + initComponents(); + getContentPane().setBackground(Color.WHITE); + lblASLError.setText(" "); + lblInputError.setText(" "); + lblOutputError.setText(" "); + txtASLDir.setText(prefs.get("aslDir", "")); + txtInputDir.setText(prefs.get("inputDir", "")); + txtOutputDir.setText(prefs.get("outputDir", "")); + cbCompileAll.setSelected(prefs.getBoolean("compileAll", false)); + cbPrettyPrinting.setSelected(prefs.getBoolean("prettyPrinting", false)); + } + + private String fileChooser(String title, FileNameExtensionFilter fileType) { + JFileChooser chooser = new JFileChooser(); + if (fileType != null) { + chooser.setFileFilter(fileType); + chooser.setAcceptAllFileFilterUsed(false); + chooser.setFileSelectionMode(0); + } else { + chooser.setFileSelectionMode(1); + } + chooser.setDialogTitle(title); + String selectedPath = ""; + if (chooser.showOpenDialog(null) == 0) { + selectedPath = chooser.getSelectedFile().toString(); + } else { + chooser.cancelSelection(); + } + return selectedPath; + } + + @SuppressWarnings("unchecked") + private void initComponents() { + + lblInput = new javax.swing.JLabel(); + txtInputDir = new javax.swing.JTextField(); + lblOutput = new javax.swing.JLabel(); + txtOutputDir = new javax.swing.JTextField(); + btnInput = new javax.swing.JButton(); + btnOutput = new javax.swing.JButton(); + lblASL = new javax.swing.JLabel(); + txtASLDir = new javax.swing.JTextField(); + btnASL = new javax.swing.JButton(); + jSeparator = new javax.swing.JSeparator(); + lblASLSmall = new javax.swing.JLabel(); + lblInputSmall = new javax.swing.JLabel(); + lblOutputSmall = new javax.swing.JLabel(); + cbCompileAll = new javax.swing.JCheckBox(); + cbPrettyPrinting = new javax.swing.JCheckBox(); + btnCompile = new javax.swing.JButton(); + lblASLError = new javax.swing.JLabel(); + lblInputError = new javax.swing.JLabel(); + lblOutputError = new javax.swing.JLabel(); + + setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + setTitle("ASL GUI"); + setMinimumSize(new java.awt.Dimension(410, 429)); + setResizable(false); + + lblInput.setFont(new java.awt.Font("Microsoft JhengHei UI Light", 0, 16)); + lblInput.setText("Input Directory:"); + lblInput.setOpaque(true); + + txtInputDir.setFont(new java.awt.Font("Segoe UI Light", 0, 16)); + + lblOutput.setFont(new java.awt.Font("Microsoft JhengHei UI Light", 0, 16)); + lblOutput.setText("Output Directory:"); + lblOutput.setOpaque(true); + + txtOutputDir.setFont(new java.awt.Font("Segoe UI Light", 0, 16)); + + btnInput.setText("..."); + btnInput.setToolTipText("Opens a dialog to select input file or directory"); + btnInput.setFocusable(false); + btnInput.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + btnInputMouseClicked(evt); + } + }); + + btnOutput.setText("..."); + btnOutput.setToolTipText("Opens a dialog to select output directory"); + btnOutput.setFocusable(false); + btnOutput.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + btnOutputMouseClicked(evt); + } + }); + + lblASL.setFont(new java.awt.Font("Microsoft JhengHei UI Light", 0, 16)); + lblASL.setText("ASL Compiler Directory"); + lblASL.setOpaque(true); + + txtASLDir.setFont(new java.awt.Font("Segoe UI Light", 0, 16)); + + btnASL.setText("..."); + btnASL.setToolTipText("Opens a dialog to select the compiler location"); + btnASL.setFocusable(false); + btnASL.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + btnASLMouseClicked(evt); + } + }); + + jSeparator.setToolTipText(""); + + lblASLSmall.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 10)); + lblASLSmall.setText("Location of the asl.exe file."); + lblASLSmall.setOpaque(true); + + lblInputSmall.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 10)); + lblInputSmall.setText("Script that should be compiled in to the output directory."); + lblInputSmall.setOpaque(true); + + lblOutputSmall.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 10)); + lblOutputSmall.setText("Directory that the compiled .sqf script(s) will be saved in."); + lblOutputSmall.setOpaque(true); + + cbCompileAll.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 11)); + cbCompileAll.setText("Compile all scripts (Directory of the selected script will be used)."); + cbCompileAll.setFocusable(false); + cbCompileAll.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + cbCompileAllStateChanged(evt); + } + }); + + cbPrettyPrinting.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 11)); + cbPrettyPrinting.setText("Activate pretty printing."); + cbPrettyPrinting.setFocusable(false); + cbPrettyPrinting.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + cbPrettyPrintingStateChanged(evt); + } + }); + + btnCompile.setFont(new java.awt.Font("Microsoft JhengHei UI Light", 0, 16)); + btnCompile.setText("Compile"); + btnCompile.setToolTipText("Opens a dialog to select output directory"); + btnCompile.setFocusable(false); + btnCompile.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + btnCompileMouseClicked(evt); + } + }); + + lblASLError.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 10)); + lblASLError.setForeground(java.awt.Color.red); + lblASLError.setText("Some error"); + + lblInputError.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 10)); + lblInputError.setForeground(java.awt.Color.red); + lblInputError.setText("Some error"); + + lblOutputError.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 10)); + lblOutputError.setForeground(java.awt.Color.red); + lblOutputError.setText("Some error"); + lblOutputError.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + lblOutputErrorMouseClicked(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jSeparator) + .addGroup(layout.createSequentialGroup() + .addGap(15, 15, 15) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lblOutputError, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(lblInputError, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(lblASLError, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lblASL) + .addComponent(lblASLSmall) + .addGroup(layout.createSequentialGroup() + .addComponent(txtASLDir, javax.swing.GroupLayout.PREFERRED_SIZE, 320, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(6, 6, 6) + .addComponent(btnASL)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(txtOutputDir, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 320, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblOutput, javax.swing.GroupLayout.Alignment.LEADING)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnOutput)) + .addComponent(lblOutputSmall) + .addComponent(cbPrettyPrinting) + .addComponent(cbCompileAll) + .addComponent(lblInput) + .addGroup(layout.createSequentialGroup() + .addComponent(txtInputDir, javax.swing.GroupLayout.PREFERRED_SIZE, 320, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnInput)) + .addComponent(lblInputSmall)) + .addGap(0, 0, Short.MAX_VALUE))) + .addGap(24, 24, 24)) + .addGroup(layout.createSequentialGroup() + .addComponent(btnCompile, javax.swing.GroupLayout.PREFERRED_SIZE, 373, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(22, 22, 22)))) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(6, 6, 6) + .addComponent(lblASL) + .addGap(3, 3, 3) + .addComponent(lblASLSmall) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(txtASLDir, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnASL, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(4, 4, 4) + .addComponent(lblASLError) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(3, 3, 3) + .addComponent(lblInput) + .addGap(3, 3, 3) + .addComponent(lblInputSmall, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(txtInputDir, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnInput, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(4, 4, 4) + .addComponent(lblInputError) + .addGap(6, 6, 6) + .addComponent(lblOutput) + .addGap(3, 3, 3) + .addComponent(lblOutputSmall, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(6, 6, 6) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(txtOutputDir, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnOutput, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(4, 4, 4) + .addComponent(lblOutputError) + .addGap(6, 6, 6) + .addComponent(cbCompileAll) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(cbPrettyPrinting) + .addGap(18, 18, 18) + .addComponent(btnCompile, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(11, 11, 11)) + ); + + pack(); + setLocationRelativeTo(null); + } + + private void btnInputMouseClicked(java.awt.event.MouseEvent evt) { + if (SwingUtilities.isLeftMouseButton(evt)) { + String path = fileChooser("Select asl script location", new FileNameExtensionFilter("Arma Scripting Language File", "asl")); + File inputDir = new File(path); + if (inputDir.exists()) { + prefs.put("inputDir", path); + txtInputDir.setText(path); + } + } + } + + private void btnOutputMouseClicked(java.awt.event.MouseEvent evt) { + if (SwingUtilities.isLeftMouseButton(evt)) { + String path = fileChooser("Select output location", null); + File outputDir = new File(path); + if (outputDir.exists() && outputDir.isDirectory()) { + prefs.put("outputDir", path); + txtOutputDir.setText(path); + } else if (!outputDir.exists()) { + lblOutputError.setText("Folder doesn't exsist! Click this message to create it."); + outputFixDir = true; + } + } + } + + private void btnASLMouseClicked(java.awt.event.MouseEvent evt) { + if (SwingUtilities.isLeftMouseButton(evt)) { + String path = fileChooser("Select 'asl.exe' location", new FileNameExtensionFilter("Executable", "exe")); + File asl = new File(path); + if (asl.exists()) { + prefs.put("aslDir", path); + txtASLDir.setText(path); + } + } + } + + private void btnCompileMouseClicked(java.awt.event.MouseEvent evt) { + if (SwingUtilities.isLeftMouseButton(evt)) { + JTextField[] dirFields = {txtASLDir, txtInputDir, txtOutputDir}; + for (byte i = 0; i < 3; i++) { + File bleh = new File(dirFields[i].getText()); + if (!bleh.exists()) { + switch (i) { + case 0: + lblASLError.setText("asl.exe isn't in this location! You can click this message to download it."); + break; + case 1: + lblInputError.setText("Script doesn't exist!"); + break; + case 2: + lblOutputError.setText("This Folder doesn't exsist! Click this message to create it."); + outputFixDir = true; + break; + } + } + + } + } + } + + private void cbCompileAllStateChanged(javax.swing.event.ChangeEvent evt) { + prefs.putBoolean("compileAll", cbCompileAll.isSelected()); + } + + private void cbPrettyPrintingStateChanged(javax.swing.event.ChangeEvent evt) { + prefs.putBoolean("prettyPrinting", cbPrettyPrinting.isSelected()); + } + + private void lblOutputErrorMouseClicked(java.awt.event.MouseEvent evt) { + if (SwingUtilities.isLeftMouseButton(evt) && outputFixDir) { + new File(txtOutputDir.getText()).mkdirs(); + outputFixDir = false; + } + } + + public static void main(String args[]) { + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { + Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); + } + UIManager.put("ToolTip.background", new ColorUIResource(255, 255, 255)); + UIManager.put("ToolTip.foreground", new ColorUIResource(87, 87, 87)); + Border lineBorder = BorderFactory.createLineBorder(new Color(118, 118, 118)); + UIManager.put("ToolTip.border", lineBorder); + Border compoundBorder = BorderFactory.createCompoundBorder(UIManager.getBorder("ToolTip.border"), BorderFactory.createEmptyBorder(0, 2, 2, 3)); + UIManager.put("ToolTip.border", compoundBorder); + java.awt.EventQueue.invokeLater(() -> { + new Main().setVisible(true); + }); + } + + private javax.swing.JButton btnASL; + private javax.swing.JButton btnCompile; + private javax.swing.JButton btnInput; + private javax.swing.JButton btnOutput; + private javax.swing.JCheckBox cbCompileAll; + private javax.swing.JCheckBox cbPrettyPrinting; + private javax.swing.JSeparator jSeparator; + private javax.swing.JLabel lblASL; + private javax.swing.JLabel lblASLError; + private javax.swing.JLabel lblASLSmall; + private javax.swing.JLabel lblInput; + private javax.swing.JLabel lblInputError; + private javax.swing.JLabel lblInputSmall; + private javax.swing.JLabel lblOutput; + private javax.swing.JLabel lblOutputError; + private javax.swing.JLabel lblOutputSmall; + private javax.swing.JTextField txtASLDir; + private javax.swing.JTextField txtInputDir; + private javax.swing.JTextField txtOutputDir; +} From 664b4357158e3217ac6ce7bfa7df3795b914ce41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ozan=20E=C4=9Fitmen?= Date: Sun, 15 Nov 2015 15:23:21 +0200 Subject: [PATCH 2/3] Beta Release Commit --- gui/ASL GUI.exe | Bin 0 -> 46574 bytes gui/README.md | 2 +- gui/src/asl/gui/DlgError.java | 83 ++++++++++++++++ gui/src/asl/gui/Main.java | 181 +++++++++++++++++++++++++--------- 4 files changed, 216 insertions(+), 50 deletions(-) create mode 100644 gui/ASL GUI.exe create mode 100644 gui/src/asl/gui/DlgError.java diff --git a/gui/ASL GUI.exe b/gui/ASL GUI.exe new file mode 100644 index 0000000000000000000000000000000000000000..86823c7f0e0e99d9649c3f7494cf6302ac8325f1 GIT binary patch literal 46574 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%0Du!Wl`WN)XdoZ%cSkRG!N|}P27-VpXzDT5W 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 literal 0 HcmV?d00001 diff --git a/gui/README.md b/gui/README.md index 0eea8ae..56f79d2 100644 --- a/gui/README.md +++ b/gui/README.md @@ -1,4 +1,4 @@ -ASL GUI +ASL GUI version =========== An optional Java interface to make the compile procces of ASL faster and more user-friendly. It's released under the MIT licence just like the core project. diff --git a/gui/src/asl/gui/DlgError.java b/gui/src/asl/gui/DlgError.java new file mode 100644 index 0000000..52f6299 --- /dev/null +++ b/gui/src/asl/gui/DlgError.java @@ -0,0 +1,83 @@ +/* + * The MIT License + * + * Copyright 2015 Ozan Egitmen. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package asl.gui; + +public class DlgError extends javax.swing.JDialog { + + boolean isAbort = true; + + public DlgError(java.awt.Frame parent, boolean modal, String errorMessage) { + super(parent, modal); + initComponents(); + lblError.setText(errorMessage); + } + + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + lblError = new javax.swing.JLabel(); + lblTitle = new javax.swing.JLabel(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + setTitle("ERROR"); + setIconImage(null); + setMinimumSize(new java.awt.Dimension(380, 150)); + setResizable(false); + setType(java.awt.Window.Type.POPUP); + + lblError.setFont(new java.awt.Font("Segoe UI Light", 0, 16)); // NOI18N + lblError.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + lblError.setText("Some error"); + + lblTitle.setFont(new java.awt.Font("Segoe UI Light", 0, 16)); // NOI18N + lblTitle.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + lblTitle.setText("asl.exe has encountered an error:"); + lblTitle.setToolTipText(""); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lblTitle, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE) + .addComponent(lblError, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(lblTitle) + .addGap(18, 18, 18) + .addComponent(lblError) + .addGap(27, 27, 27)) + ); + + pack(); + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel lblError; + private javax.swing.JLabel lblTitle; + // End of variables declaration//GEN-END:variables +} diff --git a/gui/src/asl/gui/Main.java b/gui/src/asl/gui/Main.java index bee0e78..78c2f95 100644 --- a/gui/src/asl/gui/Main.java +++ b/gui/src/asl/gui/Main.java @@ -24,7 +24,13 @@ package asl.gui; import java.awt.Color; +import java.io.BufferedReader; import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URI; +import java.net.URISyntaxException; import java.util.logging.Level; import java.util.logging.Logger; import java.util.prefs.Preferences; @@ -41,7 +47,7 @@ import javax.swing.plaf.ColorUIResource; public class Main extends javax.swing.JFrame { Preferences prefs = Preferences.userRoot().node(this.getClass().getName()); - boolean outputFixDir = false; + boolean aslFix, outputDirFix, gaveError = false; public Main() { initComponents(); @@ -76,6 +82,7 @@ public class Main extends javax.swing.JFrame { } @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents private void initComponents() { lblInput = new javax.swing.JLabel(); @@ -100,23 +107,22 @@ public class Main extends javax.swing.JFrame { setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setTitle("ASL GUI"); - setMinimumSize(new java.awt.Dimension(410, 429)); setResizable(false); - lblInput.setFont(new java.awt.Font("Microsoft JhengHei UI Light", 0, 16)); + lblInput.setFont(new java.awt.Font("Microsoft JhengHei UI Light", 0, 16)); // NOI18N lblInput.setText("Input Directory:"); lblInput.setOpaque(true); - txtInputDir.setFont(new java.awt.Font("Segoe UI Light", 0, 16)); + txtInputDir.setFont(new java.awt.Font("Segoe UI Light", 0, 16)); // NOI18N - lblOutput.setFont(new java.awt.Font("Microsoft JhengHei UI Light", 0, 16)); + lblOutput.setFont(new java.awt.Font("Microsoft JhengHei UI Light", 0, 16)); // NOI18N lblOutput.setText("Output Directory:"); lblOutput.setOpaque(true); - txtOutputDir.setFont(new java.awt.Font("Segoe UI Light", 0, 16)); + txtOutputDir.setFont(new java.awt.Font("Segoe UI Light", 0, 16)); // NOI18N btnInput.setText("..."); - btnInput.setToolTipText("Opens a dialog to select input file or directory"); + btnInput.setToolTipText("Opens a dialog to select input file"); btnInput.setFocusable(false); btnInput.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { @@ -133,11 +139,11 @@ public class Main extends javax.swing.JFrame { } }); - lblASL.setFont(new java.awt.Font("Microsoft JhengHei UI Light", 0, 16)); + lblASL.setFont(new java.awt.Font("Microsoft JhengHei UI Light", 0, 16)); // NOI18N lblASL.setText("ASL Compiler Directory"); lblASL.setOpaque(true); - txtASLDir.setFont(new java.awt.Font("Segoe UI Light", 0, 16)); + txtASLDir.setFont(new java.awt.Font("Segoe UI Light", 0, 16)); // NOI18N btnASL.setText("..."); btnASL.setToolTipText("Opens a dialog to select the compiler location"); @@ -150,20 +156,20 @@ public class Main extends javax.swing.JFrame { jSeparator.setToolTipText(""); - lblASLSmall.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 10)); + lblASLSmall.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 10)); // NOI18N lblASLSmall.setText("Location of the asl.exe file."); lblASLSmall.setOpaque(true); - lblInputSmall.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 10)); - lblInputSmall.setText("Script that should be compiled in to the output directory."); + lblInputSmall.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 10)); // NOI18N + lblInputSmall.setText("Directory of scripts that will be compiled in to the output directory."); lblInputSmall.setOpaque(true); - lblOutputSmall.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 10)); + lblOutputSmall.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 10)); // NOI18N lblOutputSmall.setText("Directory that the compiled .sqf script(s) will be saved in."); lblOutputSmall.setOpaque(true); - cbCompileAll.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 11)); - cbCompileAll.setText("Compile all scripts (Directory of the selected script will be used)."); + cbCompileAll.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 11)); // NOI18N + cbCompileAll.setText("Compile all scripts including sub folders."); cbCompileAll.setFocusable(false); cbCompileAll.addChangeListener(new javax.swing.event.ChangeListener() { public void stateChanged(javax.swing.event.ChangeEvent evt) { @@ -171,7 +177,7 @@ public class Main extends javax.swing.JFrame { } }); - cbPrettyPrinting.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 11)); + cbPrettyPrinting.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 11)); // NOI18N cbPrettyPrinting.setText("Activate pretty printing."); cbPrettyPrinting.setFocusable(false); cbPrettyPrinting.addChangeListener(new javax.swing.event.ChangeListener() { @@ -180,7 +186,7 @@ public class Main extends javax.swing.JFrame { } }); - btnCompile.setFont(new java.awt.Font("Microsoft JhengHei UI Light", 0, 16)); + btnCompile.setFont(new java.awt.Font("Microsoft JhengHei UI Light", 0, 16)); // NOI18N btnCompile.setText("Compile"); btnCompile.setToolTipText("Opens a dialog to select output directory"); btnCompile.setFocusable(false); @@ -190,15 +196,20 @@ public class Main extends javax.swing.JFrame { } }); - lblASLError.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 10)); + lblASLError.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 10)); // NOI18N lblASLError.setForeground(java.awt.Color.red); lblASLError.setText("Some error"); + lblASLError.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + lblASLErrorMouseClicked(evt); + } + }); - lblInputError.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 10)); + lblInputError.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 10)); // NOI18N lblInputError.setForeground(java.awt.Color.red); lblInputError.setText("Some error"); - lblOutputError.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 10)); + lblOutputError.setFont(new java.awt.Font("Microsoft YaHei UI", 0, 10)); // NOI18N lblOutputError.setForeground(java.awt.Color.red); lblOutputError.setText("Some error"); lblOutputError.addMouseListener(new java.awt.event.MouseAdapter() { @@ -235,14 +246,14 @@ public class Main extends javax.swing.JFrame { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(btnOutput)) .addComponent(lblOutputSmall) - .addComponent(cbPrettyPrinting) - .addComponent(cbCompileAll) .addComponent(lblInput) .addGroup(layout.createSequentialGroup() .addComponent(txtInputDir, javax.swing.GroupLayout.PREFERRED_SIZE, 320, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(btnInput)) - .addComponent(lblInputSmall)) + .addComponent(lblInputSmall) + .addComponent(cbCompileAll) + .addComponent(cbPrettyPrinting)) .addGap(0, 0, Short.MAX_VALUE))) .addGap(24, 24, 24)) .addGroup(layout.createSequentialGroup() @@ -288,41 +299,41 @@ public class Main extends javax.swing.JFrame { .addComponent(cbCompileAll) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(cbPrettyPrinting) - .addGap(18, 18, 18) + .addGap(11, 11, 11) .addComponent(btnCompile, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(11, 11, 11)) ); pack(); setLocationRelativeTo(null); - } + }// //GEN-END:initComponents - private void btnInputMouseClicked(java.awt.event.MouseEvent evt) { + private void btnInputMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnInputMouseClicked if (SwingUtilities.isLeftMouseButton(evt)) { - String path = fileChooser("Select asl script location", new FileNameExtensionFilter("Arma Scripting Language File", "asl")); + String path = fileChooser("Select input directory", null); File inputDir = new File(path); if (inputDir.exists()) { prefs.put("inputDir", path); txtInputDir.setText(path); } } - } + }//GEN-LAST:event_btnInputMouseClicked - private void btnOutputMouseClicked(java.awt.event.MouseEvent evt) { + private void btnOutputMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnOutputMouseClicked if (SwingUtilities.isLeftMouseButton(evt)) { - String path = fileChooser("Select output location", null); + String path = fileChooser("Select output directory", null); File outputDir = new File(path); if (outputDir.exists() && outputDir.isDirectory()) { prefs.put("outputDir", path); txtOutputDir.setText(path); } else if (!outputDir.exists()) { - lblOutputError.setText("Folder doesn't exsist! Click this message to create it."); - outputFixDir = true; + lblOutputError.setText("Output folder doesn't exsist! Click this message to create it."); + outputDirFix = true; } } - } + }//GEN-LAST:event_btnOutputMouseClicked - private void btnASLMouseClicked(java.awt.event.MouseEvent evt) { + private void btnASLMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnASLMouseClicked if (SwingUtilities.isLeftMouseButton(evt)) { String path = fileChooser("Select 'asl.exe' location", new FileNameExtensionFilter("Executable", "exe")); File asl = new File(path); @@ -331,46 +342,116 @@ public class Main extends javax.swing.JFrame { txtASLDir.setText(path); } } - } + }//GEN-LAST:event_btnASLMouseClicked - private void btnCompileMouseClicked(java.awt.event.MouseEvent evt) { + private void btnCompileMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnCompileMouseClicked if (SwingUtilities.isLeftMouseButton(evt)) { + String sumthin = new File(txtASLDir.getText()).getParent() + "\\asl.exe"; + if (!new File(sumthin).exists()) { + lblASLError.setText("asl.exe isn't in this location! You can click this message to download it."); + } JTextField[] dirFields = {txtASLDir, txtInputDir, txtOutputDir}; for (byte i = 0; i < 3; i++) { File bleh = new File(dirFields[i].getText()); if (!bleh.exists()) { + gaveError = true; switch (i) { case 0: lblASLError.setText("asl.exe isn't in this location! You can click this message to download it."); + aslFix = true; break; case 1: - lblInputError.setText("Script doesn't exist!"); + lblInputError.setText("This folder doesn't exist!"); break; case 2: - lblOutputError.setText("This Folder doesn't exsist! Click this message to create it."); - outputFixDir = true; + lblOutputError.setText("Output folder doesn't exsist! Click this message to create it."); + outputDirFix = true; + break; + } + return; + } + if (bleh.exists() && gaveError) { + switch (i) { + case 0: + lblASLError.setText(" "); + break; + case 1: + lblInputError.setText(" "); + break; + case 2: + lblOutputError.setText(" "); + outputDirFix = true; break; } } - + } + if (gaveError) { + return; + } + String compileAll = "", prettyPrinting = ""; + if (cbCompileAll.isSelected()) { + compileAll = "-r"; + } + if (cbPrettyPrinting.isSelected()) { + prettyPrinting = "-pretty"; + } + String asl = txtASLDir.getText(); + String input = txtInputDir.getText(); + String output = txtOutputDir.getText(); + String aslError = " "; + try { + Process aslProcess = new ProcessBuilder(asl, compileAll, prettyPrinting, input, output).start(); + InputStream is = aslProcess.getInputStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + String line; + while ((line = br.readLine()) != null) { + if (line.contains("Error")) { + aslError = line; + } + } + aslProcess.waitFor(); + if (!aslError.equals(" ")) { + DlgError error = new DlgError(this, true, aslError); + error.setLocationRelativeTo(this); + error.setVisible(true); + } + //Runtime.getRuntime().exec("cmd /c start \"" + asl + "\" " + compileAll + prettyPrinting + "\"" + input + "\" \"" + output + "\""); + //TODO: Start app in command line with parameters + } catch (IOException | InterruptedException ex) { + Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); } } - } + }//GEN-LAST:event_btnCompileMouseClicked - private void cbCompileAllStateChanged(javax.swing.event.ChangeEvent evt) { + private void cbCompileAllStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_cbCompileAllStateChanged prefs.putBoolean("compileAll", cbCompileAll.isSelected()); - } + }//GEN-LAST:event_cbCompileAllStateChanged - private void cbPrettyPrintingStateChanged(javax.swing.event.ChangeEvent evt) { + private void cbPrettyPrintingStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_cbPrettyPrintingStateChanged prefs.putBoolean("prettyPrinting", cbPrettyPrinting.isSelected()); - } + }//GEN-LAST:event_cbPrettyPrintingStateChanged - private void lblOutputErrorMouseClicked(java.awt.event.MouseEvent evt) { - if (SwingUtilities.isLeftMouseButton(evt) && outputFixDir) { + private void lblOutputErrorMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lblOutputErrorMouseClicked + if (SwingUtilities.isLeftMouseButton(evt) && outputDirFix) { new File(txtOutputDir.getText()).mkdirs(); - outputFixDir = false; + outputDirFix = false; + lblOutputError.setText(" "); } - } + }//GEN-LAST:event_lblOutputErrorMouseClicked + + private void lblASLErrorMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lblASLErrorMouseClicked + if (SwingUtilities.isLeftMouseButton(evt) && aslFix) { + try { + URI github = new URI("https://github.com/DeKugelschieber/asl/releases"); + java.awt.Desktop.getDesktop().browse(github); + } catch (URISyntaxException | IOException ex) { + Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); + } + aslFix = false; + lblASLError.setText(" "); + } + }//GEN-LAST:event_lblASLErrorMouseClicked public static void main(String args[]) { try { @@ -389,6 +470,7 @@ public class Main extends javax.swing.JFrame { }); } + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton btnASL; private javax.swing.JButton btnCompile; private javax.swing.JButton btnInput; @@ -408,4 +490,5 @@ public class Main extends javax.swing.JFrame { private javax.swing.JTextField txtASLDir; private javax.swing.JTextField txtInputDir; private javax.swing.JTextField txtOutputDir; + // End of variables declaration//GEN-END:variables } From 5bcfda10bdccf2d6b2a49f16f170ea7d6a6e677a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ozan=20E=C4=9Fitmen?= Date: Sun, 15 Nov 2015 15:24:31 +0200 Subject: [PATCH 3/3] Update README.md --- gui/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gui/README.md b/gui/README.md index 56f79d2..472d6fe 100644 --- a/gui/README.md +++ b/gui/README.md @@ -1,6 +1,6 @@ -ASL GUI version +ASL GUI version =========== An optional Java interface to make the compile procces of ASL faster and more user-friendly. It's released under the MIT licence just like the core project. -Maintained by yours truly: [654wak654](https://github.com/654wak654/) \ No newline at end of file +Maintained by yours truly: [654wak654](https://github.com/654wak654/)