diff --git a/Noisily sorted.txt b/Noisily sorted.txt new file mode 100644 index 00000000..bba9d73c --- /dev/null +++ b/Noisily sorted.txt @@ -0,0 +1,4 @@ +N true RANDOM 56 71 0 1 +N false SORTED 363 125 1 -1 +C 0 1 +C 1 2 diff --git a/backwards slightly random.txt b/backwards slightly random.txt new file mode 100644 index 00000000..a1ca0b00 --- /dev/null +++ b/backwards slightly random.txt @@ -0,0 +1,4 @@ +N false REVERSE 25 15 0 1 +N false ALMOST 275 15 1 -1 +C 0 1 +C 1 2 diff --git a/src/dialogs/CustomImageDialog.java b/src/dialogs/CustomImageDialog.java index e937a34f..7e461438 100644 --- a/src/dialogs/CustomImageDialog.java +++ b/src/dialogs/CustomImageDialog.java @@ -14,16 +14,16 @@ public CustomImageDialog() { FileNameExtensionFilter webmpImages = new FileNameExtensionFilter("WEBMP Images", "wbmp"); this.removeAllFilesOption(); - this.fileDialog.addChoosableFileFilter(allImages); - this.fileDialog.addChoosableFileFilter(jpegImages); - this.fileDialog.addChoosableFileFilter(pngImages); - this.fileDialog.addChoosableFileFilter(gifImages); - this.fileDialog.addChoosableFileFilter(bmpImages); - this.fileDialog.addChoosableFileFilter(webmpImages); + fileDialog.addChoosableFileFilter(allImages); + fileDialog.addChoosableFileFilter(jpegImages); + fileDialog.addChoosableFileFilter(pngImages); + fileDialog.addChoosableFileFilter(gifImages); + fileDialog.addChoosableFileFilter(bmpImages); + fileDialog.addChoosableFileFilter(webmpImages); - this.fileDialog.setDialogTitle("Choose an image..."); + fileDialog.setDialogTitle("Choose an image..."); - this.fileDialog.showDialog(null, "Select"); - this.file = this.fileDialog.getSelectedFile(); + fileDialog.showDialog(null, "Select"); + this.file = fileDialog.getSelectedFile(); } } \ No newline at end of file diff --git a/src/dialogs/ExportShuffleDialog.java b/src/dialogs/ExportShuffleDialog.java new file mode 100644 index 00000000..e70ca657 --- /dev/null +++ b/src/dialogs/ExportShuffleDialog.java @@ -0,0 +1,12 @@ +package dialogs; + +final public class ExportShuffleDialog extends FileDialog { + public ExportShuffleDialog() { + super(); + + fileDialog.setDialogTitle("Choose where to export the current shuffle graph..."); + + fileDialog.showSaveDialog(null); + this.file = fileDialog.getSelectedFile(); + } +} \ No newline at end of file diff --git a/src/dialogs/ImportShuffleDialog.java b/src/dialogs/ImportShuffleDialog.java new file mode 100644 index 00000000..f1d2ae2a --- /dev/null +++ b/src/dialogs/ImportShuffleDialog.java @@ -0,0 +1,12 @@ +package dialogs; + +final public class ImportShuffleDialog extends FileDialog { + public ImportShuffleDialog() { + super(); + + fileDialog.setDialogTitle("Choose where to import the current shuffle graph from..."); + + fileDialog.showOpenDialog(null); + this.file = fileDialog.getSelectedFile(); + } +} \ No newline at end of file diff --git a/src/dialogs/ImportSortDialog.java b/src/dialogs/ImportSortDialog.java index b2e0e941..9587b28a 100644 --- a/src/dialogs/ImportSortDialog.java +++ b/src/dialogs/ImportSortDialog.java @@ -8,11 +8,11 @@ public ImportSortDialog() { FileNameExtensionFilter javaFiles = new FileNameExtensionFilter("Java Source Files (.java)", "java"); this.removeAllFilesOption(); - this.fileDialog.addChoosableFileFilter(javaFiles); + fileDialog.addChoosableFileFilter(javaFiles); - this.fileDialog.setDialogTitle("Choose a sort file to import..."); + fileDialog.setDialogTitle("Choose a sort file to import..."); - this.fileDialog.showDialog(null, "Select"); - this.file = this.fileDialog.getSelectedFile(); + fileDialog.showOpenDialog(null); + this.file = fileDialog.getSelectedFile(); } } \ No newline at end of file diff --git a/src/dialogs/LoadCustomDistributionDialog.java b/src/dialogs/LoadCustomDistributionDialog.java index 47c7d24b..23c0e1e1 100644 --- a/src/dialogs/LoadCustomDistributionDialog.java +++ b/src/dialogs/LoadCustomDistributionDialog.java @@ -4,9 +4,9 @@ final public class LoadCustomDistributionDialog extends FileDialog { public LoadCustomDistributionDialog() { super(); - this.fileDialog.setDialogTitle("Choose a distribution file..."); + fileDialog.setDialogTitle("Choose a distribution file..."); - this.fileDialog.showDialog(null, "Select"); - this.file = this.fileDialog.getSelectedFile(); + fileDialog.showDialog(null, "Select"); + this.file = fileDialog.getSelectedFile(); } } \ No newline at end of file diff --git a/src/dialogs/RunScriptDialog.java b/src/dialogs/RunScriptDialog.java index 72e648b2..19dce4bc 100644 --- a/src/dialogs/RunScriptDialog.java +++ b/src/dialogs/RunScriptDialog.java @@ -4,9 +4,9 @@ final public class RunScriptDialog extends FileDialog { public RunScriptDialog() { super(); - this.fileDialog.setDialogTitle("Choose a script file..."); + fileDialog.setDialogTitle("Choose a script file..."); - this.fileDialog.showDialog(null, "Select"); - this.file = this.fileDialog.getSelectedFile(); + fileDialog.showDialog(null, "Select"); + this.file = fileDialog.getSelectedFile(); } } \ No newline at end of file diff --git a/src/dialogs/SaveArrayDialog.java b/src/dialogs/SaveArrayDialog.java index 38ba1860..01430984 100644 --- a/src/dialogs/SaveArrayDialog.java +++ b/src/dialogs/SaveArrayDialog.java @@ -1,14 +1,12 @@ package dialogs; -import javax.swing.filechooser.FileNameExtensionFilter; - final public class SaveArrayDialog extends FileDialog { public SaveArrayDialog() { super(); - this.fileDialog.setDialogTitle("Choose where to save the contents of the main array..."); + fileDialog.setDialogTitle("Choose where to save the contents of the main array..."); - this.fileDialog.showSaveDialog(null); - this.file = this.fileDialog.getSelectedFile(); + fileDialog.showSaveDialog(null); + this.file = fileDialog.getSelectedFile(); } } \ No newline at end of file diff --git a/src/dialogs/ShuffleDialog.java b/src/dialogs/ShuffleDialog.java index 8be1902b..84724f60 100644 --- a/src/dialogs/ShuffleDialog.java +++ b/src/dialogs/ShuffleDialog.java @@ -5,10 +5,12 @@ package dialogs; import java.awt.Dimension; +import java.io.IOException; import java.awt.Dialog; import javax.swing.GroupLayout; import javax.swing.JFrame; +import javax.swing.JOptionPane; import frames.AppFrame; import frames.UtilFrame; @@ -16,8 +18,12 @@ import panels.ShufflePanel; import panes.JErrorPane; import utils.Distributions; +import utils.ShuffleGraph; import utils.ShuffleInfo; import utils.Shuffles; +import utils.shuffle_utils.GraphReader; +import utils.shuffle_utils.GraphWriter; +import utils.shuffle_utils.GraphReader.MalformedGraphFileException; import panels.ShufflePanel; /* @@ -85,6 +91,7 @@ public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram reposition(); setVisible(true); + setAlwaysOnTop(false); } @Override @@ -103,6 +110,9 @@ private void initComponents() { this.shuffleEditor = new ShufflePanel(); + this.jButton1 = new javax.swing.JButton(); + this.jButton2 = new javax.swing.JButton(); + this.jScrollPane1 = new javax.swing.JScrollPane(); this.jList1 = new javax.swing.JList(); @@ -111,11 +121,27 @@ private void initComponents() { setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + jButton1.setText("Import..."); + jButton1.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(); + } + }); + + jButton2.setText("Export..."); + jButton2.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(); + } + }); + jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); jScrollPane1.setViewportView(this.jList1); + jScrollPane2.setViewportView(this.jList2); + jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); jList1.addListSelectionListener(new javax.swing.event.ListSelectionListener() { @Override @@ -153,6 +179,12 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addGap(75, 75, 75) .addComponent(this.jScrollPane2, 175, 175, 175) .addGap(75, 75, 75)) + .addGroup(layout.createSequentialGroup() + .addGap(150, 150, 150) + .addComponent(this.jButton1) + .addGap(20, 20, 20) + .addComponent(this.jButton2) + .addGap(150, 150, 150)) ); layout.setVerticalGroup( layout.createSequentialGroup() @@ -163,51 +195,64 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addComponent(this.jScrollPane1, 175, 175, 175) .addComponent(this.jScrollPane2, 175, 175, 175)) .addGap(10, 10, 10) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) + .addComponent(this.jButton1) + .addComponent(this.jButton2)) + .addGap(10, 10, 10) ); - // layout.setHorizontalGroup( - // layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) - // .addGroup(layout.createSequentialGroup() - // .addGap(20, 20, 20) - // .addComponent(this.jLabel1) - // .addGap(5, 5, 5)) - // .addGroup(layout.createSequentialGroup() - // .addComponent(this.jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) - // .addGap(20, 20, 20)) - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - // .addGap(475, 475, 475) - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) - // .addGroup(layout.createSequentialGroup() - // .addGap(20, 20, 20) - // .addComponent(this.jLabel2) - // .addGap(5, 5, 5)) - // .addGroup(layout.createSequentialGroup() - // .addComponent(this.jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) - // .addGap(20, 20, 20))) - // ); - // layout.setVerticalGroup( - // layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - // .addGroup(layout.createSequentialGroup() - // .addContainerGap() - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - // .addComponent(this.jLabel1)) - // .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) - // .addComponent(this.jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) - // .addGap(20, 20, 20)) - // .addGroup(layout.createSequentialGroup() - // .addContainerGap() - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - // .addComponent(this.jLabel2)) - // .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) - // .addComponent(this.jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) - // .addGap(20, 20, 20)) - // ); - pack(); }// //GEN-END:initComponents + private void jButton1ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerformed + FileDialog fileDialog = new ImportShuffleDialog(); + ShuffleGraph newShuffle; + try { + newShuffle = new GraphReader().read(fileDialog.file); + } catch (IOException e) { + e.printStackTrace(); + JErrorPane.invokeCustomErrorMessage("IO Error: " + e.getMessage()); + return; + } catch (MalformedGraphFileException e) { + e.printStackTrace(); + JErrorPane.invokeCustomErrorMessage("Error Parsing File: " + e.getMessage()); + return; + } catch (IllegalArgumentException e) { + e.printStackTrace(); + String message = e.getMessage(); + if (message.startsWith("No enum constant utils.")) { + message = message.substring("No enum constant utils.".length()); + if (message.startsWith("Shuffles.")) { + message = message.substring("Shuffles.".length()); + JErrorPane.invokeCustomErrorMessage("No shuffle with the ID \"" + message + "\""); + return; + } else if (message.startsWith("Distributions.")) { + message = message.substring("Distributions.".length()); + JErrorPane.invokeCustomErrorMessage("No distribution with the ID \"" + message + "\""); + return; + } + } + JErrorPane.invokeErrorMessage(e, "Import Advanced Shuffle");; + return; + } + ArrayManager.setShuffle(newShuffle); + this.shuffleEditor.graph = newShuffle; + this.shuffleEditor.repaint(); + }//GEN-LAST:event_jButton1ActionPerformed + + private void jButton2ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerformed + FileDialog fileDialog = new ExportShuffleDialog(); + try { + new GraphWriter(shuffleEditor.graph).write(fileDialog.file); + } catch (IOException e) { + e.printStackTrace(); + JErrorPane.invokeCustomErrorMessage("IO Error: " + e.getMessage()); + return; + } + JOptionPane.showMessageDialog(null, + "Successfully exported current shuffle to file \"" + fileDialog.file.getAbsolutePath() + "\"", + "Advanced Shuffle Editor", JOptionPane.INFORMATION_MESSAGE); + }//GEN-LAST:event_jButton1ActionPerformed + private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged // TODO add your handling code here: if (bypassEvents) @@ -239,6 +284,9 @@ private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws // Variables declaration - do not modify//GEN-BEGIN:variables private ShufflePanel shuffleEditor; + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + @SuppressWarnings("rawtypes") private javax.swing.JList jList1; private javax.swing.JScrollPane jScrollPane1; diff --git a/src/dialogs/SoundbankDialog.java b/src/dialogs/SoundbankDialog.java index 7d7da77b..58196aad 100644 --- a/src/dialogs/SoundbankDialog.java +++ b/src/dialogs/SoundbankDialog.java @@ -12,14 +12,14 @@ public SoundbankDialog() { FileNameExtensionFilter generalMIDI = new FileNameExtensionFilter("General MIDI (.gm)", "gm"); this.removeAllFilesOption(); - this.fileDialog.addChoosableFileFilter(allSoundbanks); - this.fileDialog.addChoosableFileFilter(soundfonts); - this.fileDialog.addChoosableFileFilter(downloadableSounds); - this.fileDialog.addChoosableFileFilter(generalMIDI); + fileDialog.addChoosableFileFilter(allSoundbanks); + fileDialog.addChoosableFileFilter(soundfonts); + fileDialog.addChoosableFileFilter(downloadableSounds); + fileDialog.addChoosableFileFilter(generalMIDI); - this.fileDialog.setDialogTitle("Choose a MIDI soundbank..."); + fileDialog.setDialogTitle("Choose a MIDI soundbank..."); - this.fileDialog.showDialog(null, "Select"); - this.file = this.fileDialog.getSelectedFile(); + fileDialog.showDialog(null, "Select"); + this.file = fileDialog.getSelectedFile(); } } \ No newline at end of file diff --git a/src/utils/shuffle_utils/GraphReader.java b/src/utils/shuffle_utils/GraphReader.java new file mode 100644 index 00000000..a9925433 --- /dev/null +++ b/src/utils/shuffle_utils/GraphReader.java @@ -0,0 +1,178 @@ +package utils.shuffle_utils; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +import utils.Distributions; +import utils.ShuffleGraph; +import utils.ShuffleInfo; +import utils.Shuffles; + +public final class GraphReader { + public final class MalformedGraphFileException extends Exception { + // public int line, column; + + public MalformedGraphFileException() { + super(); + // this.line = 0; + // this.column = 0; + } + + // public MalformedGraphFileException(int line, int column) { + // super(); + // this.line = line; + // this.column = column; + // } + + public MalformedGraphFileException(String message) { + super(message); + // this.line = 0; + // this.column = 0; + } + + // public MalformedGraphFileException(String message, int line, int column) { + // super(message); + // this.line = line; + // this.column = column; + // } + } + + private final class PartialElement { + int left, right; + + public PartialElement(int left, int right) { + this.left = left; + this.right = right; + } + } + + Scanner scanner; + ShuffleGraph result; + List partialNodes; + + public GraphReader() { + result = null; + } + + public ShuffleGraph getResult() { + return result; + } + + public ShuffleGraph read(String fileName) throws IOException, MalformedGraphFileException { + scanner = new Scanner(fileName); + try { + read(); + } finally { + scanner.close(); + } + return result; + } + + public ShuffleGraph read(File file) throws IOException, MalformedGraphFileException { + scanner = new Scanner(file); + try { + read(); + } finally { + scanner.close(); + } + return result; + } + + public ShuffleGraph read(Scanner scanner) throws IOException, MalformedGraphFileException { + this.scanner = scanner; + try { + read(); + } finally { + scanner.close(); + } + return result; + } + + private void read() throws IOException, MalformedGraphFileException { + result = new ShuffleGraph(); + partialNodes = new ArrayList<>(); + + while (scanner.hasNext()) { + String identifier = scanner.next().toUpperCase(); + switch (identifier) { + case "N": + readNode(); + break; + case "C": + readConnection(); + break; + default: + throw new MalformedGraphFileException("Invalid element type \"" + identifier + "\""); + } + } + + for (int i = 1; i < result.nodes.size(); i++) { + Node node = result.nodes.get(i); + PartialElement partial = partialNodes.get(i - 1); + node.preConnection = partial.left == -1 ? null : result.connections.get(partial.left); + node.postConnection = partial.right == -1 ? null : result.connections.get(partial.right); + } + + partialNodes = null; + } + + private void readNode() throws MalformedGraphFileException { + if (!scanner.hasNextBoolean()) { + throw new MalformedGraphFileException("Expected isDistribution in node declaration"); + } + boolean isDistribution = scanner.nextBoolean(); + if (!scanner.hasNext()) { + throw new MalformedGraphFileException("Unexpected EOF during node parsing"); + } + String name = scanner.next(); + ShuffleInfo shuffleInfo; + if (isDistribution) { + Distributions distribution = Distributions.valueOf(name); + shuffleInfo = new ShuffleInfo(distribution); + } else { + Shuffles shuffle = Shuffles.valueOf(name); + shuffleInfo = new ShuffleInfo(shuffle); + } + if (!scanner.hasNextInt()) { + throw new MalformedGraphFileException("Expected X coordinate in node declaration"); + } + int x = scanner.nextInt(); + if (!scanner.hasNextInt()) { + throw new MalformedGraphFileException("Expected Y coordinate in node declaration"); + } + int y = scanner.nextInt(); + if (!scanner.hasNextInt()) { + throw new MalformedGraphFileException("Expected preConnection ID in node declaration"); + } + int preConnectionID = scanner.nextInt(); + if (!scanner.hasNextInt()) { + throw new MalformedGraphFileException("Expected postConnection ID in node declaration"); + } + int postConnectionID = scanner.nextInt(); + + result.nodes.add(new Node(shuffleInfo, result, x, y)); + partialNodes.add(new PartialElement(preConnectionID, postConnectionID)); + } + + private void readConnection() throws MalformedGraphFileException { + if (!scanner.hasNextInt()) { + throw new MalformedGraphFileException("Expected fromNode ID in connection declaration"); + } + int fromNodeID = scanner.nextInt(); + if (!scanner.hasNextInt()) { + throw new MalformedGraphFileException("Expected toNode ID in connection declaration"); + } + int toNodeID = scanner.nextInt(); + + Node fromNode = fromNodeID == -1 ? null : result.nodes.get(fromNodeID); + Node toNode = toNodeID == -1 ? null : result.nodes.get(toNodeID); + Connection connection = new Connection(fromNode, toNode); + result.connections.add(connection); + if (fromNodeID == 0) { + fromNode.postConnection = connection; + } + } +} diff --git a/src/utils/shuffle_utils/GraphWriter.java b/src/utils/shuffle_utils/GraphWriter.java new file mode 100644 index 00000000..a65f88b6 --- /dev/null +++ b/src/utils/shuffle_utils/GraphWriter.java @@ -0,0 +1,67 @@ +package utils.shuffle_utils; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import utils.ShuffleGraph; + +public final class GraphWriter { + ShuffleGraph graph; + + public GraphWriter(ShuffleGraph graph) { + this.graph = graph; + } + + public void write(String fileName) throws IOException { + FileWriter writer = new FileWriter(fileName); + write(writer); + } + + public void write(File file) throws IOException { + FileWriter writer = new FileWriter(file); + write(writer); + } + + public void write(FileWriter writer) throws IOException { + Map nodeMap = new HashMap<>(); + Map connectionMap = new HashMap<>(); + for (int i = 0; i < graph.nodes.size(); i++) { + Node node = graph.nodes.get(i); + nodeMap.put(node, i); + } + nodeMap.put(null, -1); + for (int i = 0; i < graph.connections.size(); i++) { + Connection conn = graph.connections.get(i); + connectionMap.put(conn, i); + } + connectionMap.put(null, -1); + + for (int i = 1; i < graph.nodes.size(); i++) { + Node node = graph.nodes.get(i); + writer.write("N "); + if (node.getValue().isDistribution()) { + writer.write("true "); + writer.write(node.getValue().getDistribution().name() + " "); + } else { + writer.write("false "); + writer.write(node.getValue().getShuffle().name() + " "); + } + writer.write(node.x + " "); + writer.write(node.y + " "); + writer.write(connectionMap.get(node.preConnection) + " "); + writer.write(connectionMap.get(node.postConnection) + "\n"); + } + + for (int i = 0; i < graph.connections.size(); i++) { + Connection conn = graph.connections.get(i); + writer.write("C "); + writer.write(nodeMap.get(conn.from) + " "); + writer.write(nodeMap.get(conn.to) + "\n"); + } + + writer.close(); + } +}