diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000..8e7f21e --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,26 @@ +# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven + +name: Java CI with Maven + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 11 + uses: actions/setup-java@v3 + with: + java-version: '11' + distribution: 'temurin' + cache: maven + - name: Build with Maven + run: mvn -B package --file pom.xml diff --git a/AlgorithmVisualizer.jar b/AlgorithmVisualizer.jar deleted file mode 100644 index 75c0ef1..0000000 Binary files a/AlgorithmVisualizer.jar and /dev/null differ diff --git a/README.md b/README.md index 81453e6..a19aa74 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,15 @@ -# AlgorithmVisualizer +# algorithm-visualizer -A program for visualizing sorting algorithms. +An application for visualizing sorting algorithms. This is my freshman year summer project! Trying to get a better understanding of sorting algorithms before my Data Structures and Algorithms class this fall while applying new things i've learned such as Swing, Git, Maven, and multi-threading. +Despite this type of project being unoriginal, the code itself is original. + + + +[![AlgorithmVisualizer](https://github.com/dlarocque/AlgorithmVisualizer/blob/master/images/Startup.PNG)](https://www.youtube.com/watch?v=WDOpFcnzuaQ "AlgorithmVisualizer") + ## Installation ### Prerequisite @@ -14,28 +20,19 @@ This is my freshman year summer project! Trying to get a better understanding o ----------------------------------------------- -- Clone the project onto your system 'https://github.com/dlarocque/AlgorithmVisualizer' -- Download the .zip file from https://github.com/dlarocque/AlgorithmVisualizer and extract its contents - -*OR* - -- Download the AlgorithmVisualizer.jar executable JAR file +#### Clone -## Running - -*These instructions are directed towards Linux users* - -- Go to `C:/.../AlgorithmVisualizer-master` and enter +`git clone https://github.com/dlarocque/AlgorithmVisualizer` -`mvn clean install` +#### Download ZIP -To compile the program. +Download the .zip file from https://github.com/dlarocque/AlgorithmVisualizer and extract its contents -Once the program is built successfully, enter the following : +## Running -`mvn exec:java -Dexec.mainClass=com.example.algorithmvisualizer.Main` +*For Linux/macOS users* -Can also build and run simultaneously with : +From the root of the project, build and execute simultaneously: `mvn install exec:java -Dexec.mainClass=com.example.algorithmvisualizer.Main` @@ -43,8 +40,6 @@ Can also build and run simultaneously with : On startup, the application will open up a frame containing buttons and an unsorted array in bar form. There is a Reset button, a button for each sorting algorithm, a drop down size changer, an FPS slider, and a label showing statistics. -![Startup](https://github.com/dlarocque/AlgorithmVisualizer/blob/master/images/Startup.PNG) - _The Reset Button_ will re-shuffle the array and stop any sorting that is being done, while keeping the size set to the array. _The Sort Buttons_ will be available when sorting isn't being done. Clicking any of them will start sorting the displayed array with the selected sorting algorithm. diff --git a/src/com/example/algorithmvisualizer/AlgVisualizer.java b/src/com/example/algorithmvisualizer/AlgVisualizer.java index 5d663f3..32e76a1 100644 --- a/src/com/example/algorithmvisualizer/AlgVisualizer.java +++ b/src/com/example/algorithmvisualizer/AlgVisualizer.java @@ -10,7 +10,6 @@ * * Instructions on how to use the application are included in README.md */ - package com.example.algorithmvisualizer; import java.util.*; @@ -19,152 +18,149 @@ import javax.swing.event.*; public class AlgVisualizer implements ActionListener, ChangeListener { + private final int FPS_MIN = 2; + private final int FPS_INIT = 10; + private final int FPS_MAX = 100; + private String[] sizeOptions = {"10", "50", "100", "300", "450", "900"}; // array size options + private int n; + private int numSwaps; + private int delay; + private Integer indexComparisons; + private long startTime; // start time of a sort + private long visualizationTime; + private boolean doBubbleSort; + private boolean doInsertionSort; + private boolean doSelectionSort; + private boolean doMergeSort; + private boolean doQuickSort; + private boolean stopSort; // True if sorting is stopped + private Integer[] arr; // array that is going to be sorted + private ContentWindow frame; + private SwingWorker arrSort; - private final int FPS_MIN = 2; - private final int FPS_INIT = 10; - private final int FPS_MAX = 100; - private String[] sizeOptions = { "10", "50", "100", "300", "450", "900" }; // array size options - private int n; - private int numSwaps; - private int delay; - private Integer indexComparisons; - private long startTime; // start time of a sort - private long visualizationTime; - private boolean doBubbleSort; - private boolean doInsertionSort; - private boolean doSelectionSort; - private boolean doMergeSort; - private boolean doQuickSort; - private boolean stopSort; // True if sorting is stopped - private Integer[] arr; // array that is going to be sorted - private ContentWindow frame; - private SwingWorker arrSort; - - - /* + /* * actionPerformed(ActionEvent event) - * - * When an action is performed on a component on the JFrame that has had this + * + * When an action is performed on a component on the JFrame that has had this * classes actionListener added to it, this method will decide what to do based * on the event. - * - * When a sorting button is clicked, its - * respective boolean do(..)Sort will be set to true, and arrSort().execute. - * This will call the doInBackground() method in the arrSort object, where it - * will use the do(..)Sort variable to discover which sorting algorithm to use, - * or if there is simply a reset. - */ - public void actionPerformed(ActionEvent event) { - // Any time an action is performed, sorting is stopped - setStopSort(false); - doBubbleSort = false; - doSelectionSort = false; - doInsertionSort = false; - doMergeSort = false; - doQuickSort = false; - - // Find the source of the action + * + * When a sorting button is clicked, its respective boolean do(..)Sort will be + * set to true, and arrSort().execute. This will call the doInBackground() + * method in the arrSort object, where it will use the do(..)Sort variable to + * discover which sorting algorithm to use, or if there is simply a reset. + */ + public void actionPerformed(ActionEvent event) { + // Any time an action is performed, sorting is stopped + setStopSort(false); + doBubbleSort = false; + doSelectionSort = false; + doInsertionSort = false; + doMergeSort = false; + doQuickSort = false; + + // Find the source of the action // Is there a better way to do this? - if (event.getSource() == frame.getBubbleButton()) { - doBubbleSort = true; - arrSort.execute(); - } else if (event.getSource() == frame.getSelectionButton()) { - doSelectionSort = true; - arrSort.execute(); - } else if (event.getSource() == frame.getInsertionButton()) { - doInsertionSort = true; - arrSort.execute(); - } else if (event.getSource() == frame.getMergeButton()) { - doMergeSort = true; - arrSort.execute(); - } else if (event.getSource() == frame.getQuickButton()) { - doQuickSort = true; - arrSort.execute(); - } else if (event.getSource() == frame.getResetButton()) { - reset(); - arrSort.execute(); - } else if (event.getSource() == frame.getSizeChanger()) { - // Find what size was selected, and set n to that value - String selectedSize = (String) frame.getSizeChanger().getSelectedItem(); - n = Integer.valueOf(selectedSize); - // reset and paint the new array - reset(); - arrSort.execute(); - } - } + if (event.getSource() == frame.getBubbleButton()) { + doBubbleSort = true; + arrSort.execute(); + } else if (event.getSource() == frame.getSelectionButton()) { + doSelectionSort = true; + arrSort.execute(); + } else if (event.getSource() == frame.getInsertionButton()) { + doInsertionSort = true; + arrSort.execute(); + } else if (event.getSource() == frame.getMergeButton()) { + doMergeSort = true; + arrSort.execute(); + } else if (event.getSource() == frame.getQuickButton()) { + doQuickSort = true; + arrSort.execute(); + } else if (event.getSource() == frame.getResetButton()) { + reset(); + arrSort.execute(); + } else if (event.getSource() == frame.getSizeChanger()) { + // Find what size was selected, and set n to that value + String selectedSize = (String) frame.getSizeChanger().getSelectedItem(); + n = Integer.valueOf(selectedSize); + // reset and paint the new array + reset(); + arrSort.execute(); + } + } /* - * stateChanged(ChangeEvent e) - * - * This method is called when the FPS slider - * is shifted to change the FPS of sorting. - * - * We change the amount of delay occuring in the - * sorting to what the value of the slider was moved to. + * stateChanged(ChangeEvent e) + * + * This method is called when the FPS slider is shifted to change the FPS of + * sorting. + * + * We change the amount of delay occuring in the sorting to what the value of + * the slider was moved to. */ - @Override - public void stateChanged(ChangeEvent e) { - JSlider source = (JSlider) e.getSource(); - int fps = (int) source.getValue(); - delay = 1000 / fps; // ms - setDelay(delay); - } - - /* - * reset() - * + @Override + public void stateChanged(ChangeEvent e) { + JSlider source = (JSlider) e.getSource(); + int fps = (int) source.getValue(); + delay = 1000 / fps; // ms + setDelay(delay); + } + + /* + * reset() + * * Reset method is called whenever the user presses the reset button, or when a - * new size of array is chosen from the size changer. - * - * This method stops sorting, re-shuffles the array, clears all swapped indexes, frames painted, tracked - * time, and comparisons. It must also reset the swingWorker so that the user is - * able to see another sort. Since sort.execute() can only be called once for - * SwingWorker, we simply re-instantiate it so that we are able to call it - * again. - */ - public void reset() { - setStopSort(true); - arr = initArr(); - frame.getArrDisplay().clearSwappedIndexes(); - frame.getArrDisplay().setComplete(false); - indexComparisons = 0; - resetTime(); - setSwingWorker(new ArrSorting(this, arr, frame.getArrDisplay())); - } - - // Reset the timer on the previous sort that was done, used in the reset() - public void resetTime() { - startTime = 0; - visualizationTime = 0; - } - - public Integer[] initArr() { - Integer[] arr = new Integer[n]; - arr = fillArr(arr); - arr = shuffleArr(arr); - return arr; - } - - public Integer[] shuffleArr(Integer[] arr) { - arr = fillArr(arr); - List list = Arrays.asList(arr); - Collections.shuffle(list); - arr = list.toArray(arr); - return arr; - } - - public Integer[] fillArr(Integer[] arr) { - for (int i = 0; i < n; i++) { - arr[i] = i + 1; - } - return arr; - } - - /* + * new size of array is chosen from the size changer. + * + * This method stops sorting, re-shuffles the array, clears all swapped indexes, + * frames painted, tracked time, and comparisons. It must also reset the + * swingWorker so that the user is able to see another sort. Since + * sort.execute() can only be called once for SwingWorker, we simply + * re-instantiate it so that we are able to call it again. + */ + public void reset() { + setStopSort(true); + arr = initArr(); + frame.getArrDisplay().clearSwappedIndexes(); + frame.getArrDisplay().setComplete(false); + indexComparisons = 0; + resetTime(); + setSwingWorker(new ArrSorting(this, arr, frame.getArrDisplay())); + } + + // Reset the timer on the previous sort that was done, used in the reset() + public void resetTime() { + startTime = 0; + visualizationTime = 0; + } + + public Integer[] initArr() { + Integer[] arr = new Integer[n]; + arr = fillArr(arr); + arr = shuffleArr(arr); + return arr; + } + + public Integer[] shuffleArr(Integer[] arr) { + arr = fillArr(arr); + List list = Arrays.asList(arr); + Collections.shuffle(list); + arr = list.toArray(arr); + return arr; + } + + public Integer[] fillArr(Integer[] arr) { + for (int i = 0; i < n; i++) { + arr[i] = i + 1; + } + return arr; + } + + /* * updatePerformance() - * - * This method will be called every time that the frame is updated in order to - * update our performance statistics. + * + * This method will be called every time that the frame is updated in order to + * update our performance statistics. * * Finds the values for each performance statistic being tracked (number of * swaps, number of comparisons, visualization time, sorting time), formats them @@ -172,151 +168,156 @@ public Integer[] fillArr(Integer[] arr) { * * frame.pack() makes sure that our new text will fit in the frame, and will * adjust if it does not. - */ - public void updatePerformance() { - numSwaps = frame.getArrDisplay().getSwappedIndexes().size(); - - if (stopSort) { - resetTime(); - } else { - if(!frame.getArrDisplay().isComplete() && !getSort().equals("Not Sorting") && (frame.getArrDisplay().getNumChunks() == 0 || frame.getArrDisplay().getNumChunks() > 1)) { + */ + public void updatePerformance() { + numSwaps = frame.getArrDisplay().getSwappedIndexes().size(); + + if (stopSort) { + resetTime(); + } else { + if (!frame.getArrDisplay().isComplete() && !getSort().equals("Not Sorting") + && (frame.getArrDisplay().getNumChunks() == 0 || frame.getArrDisplay().getNumChunks() > 1)) { visualizationTime = System.currentTimeMillis() - startTime; } } - String performance = String.format( - "Index Comparisons : %d Index Swaps : %d Visualization Time : %dms", - indexComparisons, numSwaps, visualizationTime); - frame.getPerformanceLabel().setText(performance); - frame.pack(); - } - - public Integer[] getArr() { - return arr; - } - - public void setArr(Integer[] arr) { - this.arr = arr; - } - - public void setN(int n) { - this.n = n; - } - - public ContentWindow getFrame() { - return frame; - } - - public void setFrame(ContentWindow frame) { - this.frame = frame; - } - - public SwingWorker getArrSorting() { - return arrSort; - } - - // Re-instantiates the SwingWorker so that execute() can be called again. - public void setSwingWorker(SwingWorker arrSort) { - this.arrSort = arrSort; - } - - public void setSort(String sort) { - if (sort.equals("Bubble Sort")) { - doBubbleSort = true; - } else if (sort.equals("Insertion Sort")) { - doInsertionSort = true; - } else if (sort.equals("Selection Sort")) { - doSelectionSort = true; - } else if (sort.equals("Merge Sort")) { - doMergeSort = true; - } else if (sort.equals("Quick Sort")) { - doQuickSort = true; - } - } - - /* + String performance = String.format("Index Comparisons : %d Index Swaps : %d Visualization Time : %dms", + indexComparisons, numSwaps, visualizationTime); + frame.getPerformanceLabel().setText(performance); + frame.pack(); + } + + public Integer[] getArr() { + return arr; + } + + public void setArr(Integer[] arr) { + this.arr = arr; + } + + public void setN(int n) { + this.n = n; + } + + public ContentWindow getFrame() { + return frame; + } + + public void setFrame(ContentWindow frame) { + this.frame = frame; + } + + public SwingWorker getArrSorting() { + return arrSort; + } + + // Re-instantiates the SwingWorker so that execute() can be called again. + public void setSwingWorker(SwingWorker arrSort) { + this.arrSort = arrSort; + } + + public void setSort(String sort) { + if (sort.equals("Bubble Sort")) { + doBubbleSort = true; + } else if (sort.equals("Insertion Sort")) { + doInsertionSort = true; + } else if (sort.equals("Selection Sort")) { + doSelectionSort = true; + } else if (sort.equals("Merge Sort")) { + doMergeSort = true; + } else if (sort.equals("Quick Sort")) { + doQuickSort = true; + } + } + + /* * getSort() returns a string containing the sorting algorithm that is currently * being used to sort the array. - */ - public String getSort() { - String sort = "Not Sorting"; - if (doBubbleSort) - sort = "Bubble Sort"; - if (doInsertionSort) - sort = "Insertion Sort"; - if (doSelectionSort) - sort = "Selection Sort"; - if (doMergeSort) - sort = "Merge Sort"; - if (doQuickSort) - sort = "Quick Sort"; - return sort; - } - - /* + */ + public String getSort() { + String sort = "Not Sorting"; + if (doBubbleSort) { + sort = "Bubble Sort"; + } + if (doInsertionSort) { + sort = "Insertion Sort"; + } + if (doSelectionSort) { + sort = "Selection Sort"; + } + if (doMergeSort) { + sort = "Merge Sort"; + } + if (doQuickSort) { + sort = "Quick Sort"; + } + return sort; + } + + /* * Returns the boolean value representing the status of the application. If * there is currently a sorting algorithm being used, it will return false. - */ - public boolean stopSort() { - return stopSort; - } + */ + public boolean stopSort() { + return stopSort; + } - /* + /* * Since the availability of the buttons is based on the stopSort variable, we * control them from this setter method. If we want to stop sorting, we enable * all of the sorting buttons again, if we are starting a sorting algorithm, * disable them. - */ - public void setStopSort(boolean toSet) { - frame.setSortButtons(toSet); - stopSort = toSet; - } - - public Integer getIndexComparisons() { - return indexComparisons; - } - - public void setIndexComparisons(int indexComparisons) { - this.indexComparisons = indexComparisons; - } - - public void setStartTime(long startTime) { - this.startTime = startTime; - } - - public int getNumSwaps() { - return numSwaps; - } - - public void setNumSwaps(int numSwaps) { - this.numSwaps = numSwaps; - } - - public int getDelay() { - return delay; - } - - public void setDelay(int delay) { - this.delay = delay; - } - - public String[] getSizeOptions() { - return sizeOptions; - } - - public void setSizeOptions(String[] sizeOptions) { - this.sizeOptions = sizeOptions; - } - - public int getMaxFPS() { - return FPS_MAX; - } - - public int getInitFPS() { - return FPS_INIT; - } - - public int getMinFPS() { - return FPS_MIN; - } + */ + public void setStopSort(boolean toSet) { + frame.setSortButtons(toSet); + stopSort = toSet; + } + + public Integer getIndexComparisons() { + return indexComparisons; + } + + public void setIndexComparisons(int indexComparisons) { + this.indexComparisons = indexComparisons; + } + + public void setStartTime(long startTime) { + this.startTime = startTime; + } + + public int getNumSwaps() { + return numSwaps; + } + + public void setNumSwaps(int numSwaps) { + this.numSwaps = numSwaps; + } + + public int getDelay() { + return delay; + } + + public void setDelay(int delay) { + this.delay = delay; + } + + public String[] getSizeOptions() { + return sizeOptions; + } + + public void setSizeOptions(String[] sizeOptions) { + this.sizeOptions = sizeOptions; + } + + public int getMaxFPS() { + return FPS_MAX; + } + + public int getInitFPS() { + return FPS_INIT; + } + + public int getMinFPS() { + return FPS_MIN; + } } diff --git a/src/com/example/algorithmvisualizer/ArrDisplay.java b/src/com/example/algorithmvisualizer/ArrDisplay.java index 9bd146c..d5e2d07 100644 --- a/src/com/example/algorithmvisualizer/ArrDisplay.java +++ b/src/com/example/algorithmvisualizer/ArrDisplay.java @@ -10,7 +10,6 @@ * * Instructions on how to use the application are included in README.md */ - package com.example.algorithmvisualizer; import java.awt.*; @@ -19,23 +18,23 @@ public class ArrDisplay extends JComponent { - private static final long serialVersionUID = 1L; - private int swappedIndex1; - private int swappedIndex2; - private int numChunks; // amount of frames painted since the array was shuffled - private boolean isComplete; // if the array is sorted - private ArrayList swappedIndexes; - private Integer[] arr; - private AlgVisualizer algVisualizer; - private ContentWindow frame; - - public ArrDisplay(AlgVisualizer algVisualizer, ContentWindow frame) { - this.algVisualizer = algVisualizer; - this.frame = frame; - swappedIndexes = new ArrayList(); - } - - /* + private static final long serialVersionUID = 1L; + private int swappedIndex1; + private int swappedIndex2; + private int numChunks; // amount of frames painted since the array was shuffled + private boolean isComplete; // if the array is sorted + private ArrayList swappedIndexes; + private Integer[] arr; + private AlgVisualizer algVisualizer; + private ContentWindow frame; + + public ArrDisplay(AlgVisualizer algVisualizer, ContentWindow frame) { + this.algVisualizer = algVisualizer; + this.frame = frame; + swappedIndexes = new ArrayList(); + } + + /* * We override the paintComponent method to allow us to render our own * visualization of the array in bar graph form. This method is called through * the use of the repaint() method that is called in the SwingWorkers publish() @@ -49,74 +48,76 @@ public ArrDisplay(AlgVisualizer algVisualizer, ContentWindow frame) { * were swapped during sorting. Since we always draw the most recent chunk, * numChunks will always represent the number of the array clone we're drawing, * so using that to get the correct index in swappedIndexes will work. - */ - @Override - public void paintComponent(Graphics g) { - Graphics2D graphics2d = (Graphics2D) g; - graphics2d.setColor(Color.DARK_GRAY); - graphics2d.fillRect(0, 0, frame.getArrDisplayWidth(), frame.getArrDisplayHeight()); - if (algVisualizer.getSort().equals("Not Sorting") || isComplete) { - swappedIndex1 = -1; - swappedIndex2 = -1; - } else if (!algVisualizer.stopSort()) { - swappedIndex1 = swappedIndexes.get(numChunks)[0]; - swappedIndex2 = swappedIndexes.get(numChunks)[1]; - } - // Iterate through the array and draw every index - for (int i = 0; i < arr.length; i++) { - int width = (int) (frame.getArrDisplayWidth() / (double) arr.length); - int height = arr[i] * ((int) (frame.getArrDisplayHeight() / arr.length)); - int x = i * width; - int y = frame.getArrDisplayHeight() - height; - if (i == swappedIndex1 && !algVisualizer.stopSort()) { - graphics2d.setColor(Color.RED); - } else if (i == swappedIndex2 && !algVisualizer.stopSort()) { - graphics2d.setColor(Color.BLUE); - } else if (isComplete) { - graphics2d.setColor(Color.GREEN); - } else { - graphics2d.setColor(Color.WHITE); - } - // Draw the current indexes bar - graphics2d.fillRect(x, y, width, height); - } - algVisualizer.updatePerformance(); - } - - public ArrayList getSwappedIndexes() { - return swappedIndexes; - } - - // Add a pair of swapped indexes to the end of the list - public void addSwappedIndexes(int swappedIndex1, int swappedIndex2) { - swappedIndexes.add(new Integer[] { swappedIndex1, swappedIndex2 }); - } - - public void clearSwappedIndexes() { - swappedIndexes = new ArrayList(); - } - - public void setNumChunk(int numChunks) { - this.numChunks = numChunks; - } - - public int getNumChunks() { - return numChunks; - } - - public boolean isComplete() { - return isComplete; - } - - public void setComplete(boolean complete) { - this.isComplete = complete; - } - - public Integer[] getArr() { - return arr; - } - - public void setArr(Integer[] arr) { - this.arr = arr; - } + */ + @Override + public void paintComponent(Graphics g) { + Graphics2D graphics2d = (Graphics2D) g; + graphics2d.setColor(Color.DARK_GRAY); + graphics2d.fillRect(0, 0, frame.getArrDisplayWidth(), frame.getArrDisplayHeight()); + + if (algVisualizer.getSort().equals("Not Sorting") || isComplete) { + swappedIndex1 = -1; + swappedIndex2 = -1; + } else if (!algVisualizer.stopSort()) { + swappedIndex1 = swappedIndexes.get(numChunks)[0]; + swappedIndex2 = swappedIndexes.get(numChunks)[1]; + } + // Iterate through the array and draw every index + for (int i = 0; i < arr.length; i++) { + int width = (int) (frame.getArrDisplayWidth() / (double) arr.length); + int height = arr[i] * ((int) (frame.getArrDisplayHeight() / arr.length)); + int x = i * width; + int y = frame.getArrDisplayHeight() - height; + + if (i == swappedIndex1 && !algVisualizer.stopSort()) { + graphics2d.setColor(Color.RED); + } else if (i == swappedIndex2 && !algVisualizer.stopSort()) { + graphics2d.setColor(Color.BLUE); + } else if (isComplete) { + graphics2d.setColor(Color.GREEN); + } else { + graphics2d.setColor(Color.WHITE); + } + // Draw the current indexes bar + graphics2d.fillRect(x, y, width, height); + } + algVisualizer.updatePerformance(); + } + + public ArrayList getSwappedIndexes() { + return swappedIndexes; + } + + // Add a pair of swapped indexes to the end of the list + public void addSwappedIndexes(int swappedIndex1, int swappedIndex2) { + swappedIndexes.add(new Integer[]{swappedIndex1, swappedIndex2}); + } + + public void clearSwappedIndexes() { + swappedIndexes = new ArrayList(); + } + + public void setNumChunk(int numChunks) { + this.numChunks = numChunks; + } + + public int getNumChunks() { + return numChunks; + } + + public boolean isComplete() { + return isComplete; + } + + public void setComplete(boolean complete) { + this.isComplete = complete; + } + + public Integer[] getArr() { + return arr; + } + + public void setArr(Integer[] arr) { + this.arr = arr; + } } diff --git a/src/com/example/algorithmvisualizer/ArrSorting.java b/src/com/example/algorithmvisualizer/ArrSorting.java index 7e25206..d6277ea 100644 --- a/src/com/example/algorithmvisualizer/ArrSorting.java +++ b/src/com/example/algorithmvisualizer/ArrSorting.java @@ -1,16 +1,15 @@ /* * An application that visualizes sorting algorithms through bar graphs. - * + * * Author : Daniel La Rocque - * + * * Date started : April 28th, 2020 - * + * * This project is licensed under the MIT License. * See LICENSE.txt for more details - * + * * Instructions on how to use the application are included in README.md */ - package com.example.algorithmvisualizer; import java.util.*; @@ -18,20 +17,20 @@ public class ArrSorting extends SwingWorker { - private int n; - private Integer[] arr; - private AlgVisualizer algVisualizer; - private ArrDisplay arrDisplay; - private int numChunks; + private int n; + private Integer[] arr; + private AlgVisualizer algVisualizer; + private ArrDisplay arrDisplay; + private int numChunks; - public ArrSorting(AlgVisualizer algVisualizer, Integer[] arr, ArrDisplay arrDisplay) { - this.algVisualizer = algVisualizer; - this.arr = arr; - this.arrDisplay = arrDisplay; - this.n = arr.length; - } + public ArrSorting(AlgVisualizer algVisualizer, Integer[] arr, ArrDisplay arrDisplay) { + this.algVisualizer = algVisualizer; + this.arr = arr; + this.arrDisplay = arrDisplay; + this.n = arr.length; + } - /* + /* * doInBackground() can only be called once by calling execute() This method * determines what to do when an action is done. We use if statements to * determine what buttons was clicked, helping determine what action to do next. @@ -39,350 +38,328 @@ public ArrSorting(AlgVisualizer algVisualizer, Integer[] arr, ArrDisplay arrDisp * that it is able to sort the next time execute() is called. If a sorting * algorithm was clicked, simply perform that sorting algorithm. Make sure to * set the start and end times for the performance window at the end of sorting. - */ - @Override - protected Void doInBackground() throws Exception { - // COULD BE MORE DRY ? - if (algVisualizer.stopSort()) { - publish(arr.clone()); - sleep(); - algVisualizer.setSwingWorker(new ArrSorting(algVisualizer, arr, arrDisplay)); - } else { - algVisualizer.setStartTime(System.currentTimeMillis()); - if (algVisualizer.getSort().equals("Bubble Sort")) { - bubbleSort(); - } else if (algVisualizer.getSort().equals("Insertion Sort")) { - insertionSort(); - } else if (algVisualizer.getSort().equals("Selection Sort")) { - selectionSort(); - } else if (algVisualizer.getSort().equals("Merge Sort")) { - mergeSort(0, arr.length - 1); - } else if (algVisualizer.getSort().equals("Quick Sort")) { - quickSort(0, arr.length - 1); - } - } - return null; - } - - /* + */ + @Override + protected Void doInBackground() throws Exception { + if (algVisualizer.stopSort()) { + publish(arr.clone()); + sleep(); + algVisualizer.setSwingWorker(new ArrSorting(algVisualizer, arr, arrDisplay)); + } else { + algVisualizer.setStartTime(System.currentTimeMillis()); + if (algVisualizer.getSort().equals("Bubble Sort")) { + bubbleSort(); + } else if (algVisualizer.getSort().equals("Insertion Sort")) { + insertionSort(); + } else if (algVisualizer.getSort().equals("Selection Sort")) { + selectionSort(); + } else if (algVisualizer.getSort().equals("Merge Sort")) { + mergeSort(0, arr.length - 1); + } else if (algVisualizer.getSort().equals("Quick Sort")) { + quickSort(0, arr.length - 1); + } + } + return null; + } + + /* * This method accepts a clone of the array that was sent to it as a parameter * from the sorting algorithms. If this method isn't finished executing by the * time that another publish(Arr.clone()) is made, it will send in the array * clone at the end of the list of chunks. - * + * * Since the repaint() method can not keep up with the amount of chunks sent in * from the sorting algorithms when there is very low delay time (Repaint time * depends on the system), it will only draw a fraction of the array clones sent * to it. - * + * * To make sure that the colored bars representing the swapped indexes are in * sync with the array being painted, we track the amount of chunks sent, and * send it to arrDisplay, so that whenever repaint() has the opportunity to * execute, the chunk number of the array clone that is being drawn will be * represented by numChunk, which will be used to get the swappedIndexes from * the list. ( numChunk are swappedIndexes.size() are always equal. ) - */ - @Override - protected void process(List chunks) { - for (int i = 0; i < chunks.size(); i++) { - // Paint each cloned array that was sent as a chunk - arrDisplay.setNumChunk(numChunks++); - arrDisplay.setArr(chunks.get(i)); - arrDisplay.repaint(); - } - } - - /* - * sleep() - * - * This method is called when a sorting algorithm is being - * visualized and the algorithm needs to sleep to slow down - * the visualization of sorting. + */ + @Override + protected void process(List chunks) { + int chunksSize = chunks.size(); + for (int i = 0; i < chunksSize; i++) { + // Paint each cloned array that was sent as a chunk + arrDisplay.setNumChunk(numChunks++); + arrDisplay.setArr(chunks.get(0)); + chunks.remove(0); + arrDisplay.repaint(); + } + } + + /* + * sleep() + * + * This method is called when a sorting algorithm is being visualized and the + * algorithm needs to sleep to slow down the visualization of sorting. */ private void sleep() { - try { - + try { Thread.sleep(algVisualizer.getDelay()); - - } catch (InterruptedException e) { - - e.printStackTrace(); - + } catch (InterruptedException e) { + e.printStackTrace(); } - } + } - /* + /* * All of the sorting algorithms below are constantly checking in the loops to * see if sorting has been stopped by a reset. If sorting has been stopped, the * if statement will be true and the sorting method will be terminated. - * + * * After every index comparison, we add +1 to the total number of index * comparisons. - * + * * After every index swap, we add the pair of indexes swapped to the list in * arrDisplay for them to be drawn. We then call publish() and send a clone of * the array as a chunk to the process(List<> Chunks) method above, where it * will be painted in the frame. - */ - - private void bubbleSort() { - for (int i = 0; i < n - 1; i++) { - - if (algVisualizer.stopSort()) - break; - + */ + private void bubbleSort() { + for (int i = 0; i < n - 1; i++) { + if (algVisualizer.stopSort()) { + break; + } for (int j = 0; j < n - i - 1; j++) { - if (algVisualizer.stopSort()) { - break; - } else { - + break; + } else { algVisualizer.setIndexComparisons(algVisualizer.getIndexComparisons() + 1); - + if (arr[j] > arr[j + 1]) { - int temp = arr[j]; - arr[j] = arr[j + 1]; - arr[j + 1] = temp; - + arr[j] = arr[j + 1]; + arr[j + 1] = temp; + arrDisplay.addSwappedIndexes(j, j + 1); publish(arr.clone()); - sleep(); + sleep(); } - } - } - } - // Sorting complete, loop done - if (!algVisualizer.stopSort()) { - arrDisplay.setComplete(true); + } + } + } + // Sorting complete, loop done + if (!algVisualizer.stopSort()) { + arrDisplay.setComplete(true); publish(arr.clone()); - sleep(); + sleep(); + } + } + + private void selectionSort() { + for (int i = 0; i < n - 1; i++) { + if (algVisualizer.stopSort()) { + break; + } + int min_idx = i; + for (int j = i + 1; j < n; j++) { + algVisualizer.setIndexComparisons(algVisualizer.getIndexComparisons() + 1); + if (arr[j] < arr[min_idx]) { + min_idx = j; + } + } + int temp = arr[min_idx]; + arr[min_idx] = arr[i]; + arr[i] = temp; + + arrDisplay.addSwappedIndexes(min_idx, i); + publish(arr.clone()); + sleep(); + } + if (!algVisualizer.stopSort()) { + arrDisplay.setComplete(true); + publish(arr.clone()); + sleep(); + } + } + + private void insertionSort() { + for (int i = 1; i < n; ++i) { + if (algVisualizer.stopSort()) { + break; + } + int key = arr[i]; + int j = i - 1; + while (j >= 0 && arr[j] > key) { // compare arr[j] and arr[i] + if (algVisualizer.stopSort()) { + break; + } + algVisualizer.setIndexComparisons(algVisualizer.getIndexComparisons() + 1); + arr[j + 1] = arr[j]; + j = j - 1; + arrDisplay.addSwappedIndexes(j, j + 1); + publish(arr.clone()); + sleep(); + } + + algVisualizer.setIndexComparisons(algVisualizer.getIndexComparisons() + 1); + arr[j + 1] = key; + } + if (!algVisualizer.stopSort()) { + arrDisplay.setComplete(true); + publish(arr.clone()); + sleep(); + } + } + + private void mergeSort(int l, int r) { + if (algVisualizer.getSort().equals("Merge Sort") && !algVisualizer.stopSort()) { // Needed because of recursion + if (l < r) { + int m = (l + r) / 2; + mergeSort(l, m); + mergeSort(m + 1, r); + merge(l, m, r); + } + if (isSorted() && !algVisualizer.stopSort()) { + arrDisplay.setComplete(true); + publish(arr.clone()); + sleep(); + + } } - } - - private void selectionSort() { - for (int i = 0; i < n - 1; i++) { - if (algVisualizer.stopSort()) - break; - int min_idx = i; - for (int j = i + 1; j < n; j++) { - algVisualizer.setIndexComparisons(algVisualizer.getIndexComparisons() + 1); - if (arr[j] < arr[min_idx]) - min_idx = j; - } - // Swap arr[min_idx] and arr[i] - int temp = arr[min_idx]; - arr[min_idx] = arr[i]; - arr[i] = temp; - // Add a pair of swapped indexes - arrDisplay.addSwappedIndexes(min_idx, i); - publish(arr.clone()); - sleep(); - } - if (!algVisualizer.stopSort()) { - arrDisplay.setComplete(true); - publish(arr.clone()); - sleep(); - } - } - - private void insertionSort() { - for (int i = 1; i < n; ++i) { - if (algVisualizer.stopSort()) - break; - int key = arr[i]; - int j = i - 1; - while (j >= 0 && arr[j] > key) { // compare arr[j] and arr[i] - if (algVisualizer.stopSort()) - break; - algVisualizer.setIndexComparisons(algVisualizer.getIndexComparisons() + 1); - // swap arr[j] and arr[j + 1] - arr[j + 1] = arr[j]; - j = j - 1; - arrDisplay.addSwappedIndexes(j, j + 1); - publish(arr.clone()); - sleep(); - } - // Add a pair of swapped indexes - algVisualizer.setIndexComparisons(algVisualizer.getIndexComparisons() + 1); - arr[j + 1] = key; - } - if (!algVisualizer.stopSort()) { - arrDisplay.setComplete(true); - publish(arr.clone()); - sleep(); - } - } - - private void mergeSort(int l, int r) { - if (algVisualizer.getSort().equals("Merge Sort") && !algVisualizer.stopSort()) { // Needed because of recursion - if (l < r) { - // Find the middle point - int m = (l + r) / 2; - // Sort first and second halves - mergeSort(l, m); - mergeSort(m + 1, r); - // Merge the sorted halves - merge(l, m, r); - } - // If sorting is done and a reset has not been done, repaint one more time - if (isSorted() && !algVisualizer.stopSort()) { - arrDisplay.setComplete(true); - publish(arr.clone()); - sleep(); - - } - } - } - - private void merge(int l, int m, int r) { - if (algVisualizer.getSort().equals("Merge Sort") && !algVisualizer.stopSort()) { // Needed because of recursion - + } + + private void merge(int l, int m, int r) { + if (algVisualizer.getSort().equals("Merge Sort") && !algVisualizer.stopSort()) { // Needed because of recursion int n1 = m - l + 1; - int n2 = r - m; - + int n2 = r - m; int L[] = new int[n1]; - int R[] = new int[n2]; - + int R[] = new int[n2]; + for (int i = 0; i < n1; ++i) { - L[i] = arr[l + i]; + L[i] = arr[l + i]; } - for (int j = 0; j < n2; ++j) { - R[j] = arr[m + 1 + j]; + for (int j = 0; j < n2; ++j) { + R[j] = arr[m + 1 + j]; } - - int i = 0, j = 0; - int k = l; - while (i < n1 && j < n2) { - + int i = 0, j = 0; + int k = l; + while (i < n1 && j < n2) { + if (algVisualizer.stopSort()) { // necessary to check this within every loop? - break; + break; } + algVisualizer.setIndexComparisons(algVisualizer.getIndexComparisons() + 1); - algVisualizer.setIndexComparisons(algVisualizer.getIndexComparisons() + 1); - if (L[i] <= R[j]) { - arr[k] = L[i]; - i++; - + arr[k] = L[i]; + i++; + arrDisplay.addSwappedIndexes(k, k + i); - publish(arr.clone()); - sleep(); - + publish(arr.clone()); + sleep(); + } else { - arr[k] = R[j]; - j++; - + arr[k] = R[j]; + j++; + arrDisplay.addSwappedIndexes(k, k + j); - publish(arr.clone()); - sleep(); + publish(arr.clone()); + sleep(); } - k++; - } - + k++; + } + while (i < n1) { - if (algVisualizer.stopSort()) { - break; + break; } + arr[k] = L[i]; - arr[k] = L[i]; - arrDisplay.addSwappedIndexes(k, k + i); - publish(arr.clone()); - sleep(); - + publish(arr.clone()); + sleep(); + i++; - k++; - } - + k++; + } + while (j < n2) { - if (algVisualizer.stopSort()) { - break; + break; } + arr[k] = R[j]; - arr[k] = R[j]; - arrDisplay.addSwappedIndexes(k, k + j); - publish(arr.clone()); - sleep(); - + publish(arr.clone()); + sleep(); + j++; - k++; - } - } - } - - private void quickSort(int low, int high) { - if (algVisualizer.getSort().equals("Quick Sort") && !algVisualizer.stopSort()) { // Needed because of recursion - if (low < high) { - - int pi = partition(low, high); + k++; + } + } + } - quickSort(low, pi - 1); - quickSort(pi + 1, high); - } - if (isSorted() && !algVisualizer.stopSort()) { + private void quickSort(int low, int high) { + if (algVisualizer.getSort().equals("Quick Sort") && !algVisualizer.stopSort()) { // Needed because of recursion + if (low < high) { + int pi = partition(low, high); + quickSort(low, pi - 1); + quickSort(pi + 1, high); + } + if (isSorted() && !algVisualizer.stopSort()) { arrDisplay.setComplete(true); publish(arr.clone()); - sleep(); - } - } - } - + sleep(); + } + } + } + // quicksort - private int partition(int low, int high) { - if (algVisualizer.getSort().equals("Quick Sort") && !algVisualizer.stopSort()) { // Needed because of recursion - + private int partition(int low, int high) { + if (algVisualizer.getSort().equals("Quick Sort") && !algVisualizer.stopSort()) { // Needed because of recursion int pivot = arr[high]; - int i = (low - 1); - + int i = (low - 1); + for (int j = low; j < high; j++) { - + if (algVisualizer.getSort().equals("Quick Sort") && !algVisualizer.stopSort()) { - algVisualizer.setIndexComparisons(algVisualizer.getIndexComparisons() + 1); - + algVisualizer.setIndexComparisons(algVisualizer.getIndexComparisons() + 1); + if (arr[j] < pivot) { - i++; - int temp = arr[i]; - arr[i] = arr[j]; - arr[j] = temp; - + i++; + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + arrDisplay.addSwappedIndexes(i, j); - publish(arr.clone()); - sleep(); - } - } - } - - if (algVisualizer.getSort().equals("Quick Sort") && !algVisualizer.stopSort()) { - // swap arr[i+1] and arr[high] (or pivot) - int temp = arr[i + 1]; - arr[i + 1] = arr[high]; - arr[high] = temp; - arrDisplay.addSwappedIndexes(i + 1, high); - publish(arr.clone()); - sleep(); - } - return i + 1; - } - return 0; - } - - /* + publish(arr.clone()); + sleep(); + } + } + } + + if (algVisualizer.getSort().equals("Quick Sort") && !algVisualizer.stopSort()) { + // swap arr[i+1] and arr[high] (or pivot) + int temp = arr[i + 1]; + arr[i + 1] = arr[high]; + arr[high] = temp; + arrDisplay.addSwappedIndexes(i + 1, high); + publish(arr.clone()); + sleep(); + } + return i + 1; + } + return 0; + } + + /* * This method tells us if the array is sorted or not. Used to check in the * recursive sorts. - */ - private boolean isSorted() { - boolean isSorted = true; - + */ + private boolean isSorted() { + boolean isSorted = true; + for (int i = 0; i < arr.length - 1; i++) { - if (arr[i] > arr[i + 1]) { - isSorted = false; + if (arr[i] > arr[i + 1]) { + isSorted = false; } - } - return isSorted; - } + } + return isSorted; + } } diff --git a/src/com/example/algorithmvisualizer/ContentWindow.java b/src/com/example/algorithmvisualizer/ContentWindow.java index 223c8f7..fb158d1 100644 --- a/src/com/example/algorithmvisualizer/ContentWindow.java +++ b/src/com/example/algorithmvisualizer/ContentWindow.java @@ -8,91 +8,87 @@ */ public class ContentWindow extends JFrame { - private static final long serialVersionUID = 1L; - private int arrDisplayHeight; - private int arrDisplayWidth; - private int contentWidth; - private int contentHeight; - private AlgVisualizer algVisualizer; - private JPanel arrPanel; - private ArrDisplay arrDisplay; - private JPanel buttonPanel; - private JButton resetButton; - private JButton bubbleButton; - private JButton insertionButton; - private JButton selectionButton; - private JButton mergeButton; - private JButton quickButton; - private JComboBox sizeChanger; - private JSlider FPSslider; - private JLabel performanceLabel; - - public ContentWindow(AlgVisualizer algVisualizer) { - super("Algorithm Visualizer"); // Set the name of the frame - this.algVisualizer = algVisualizer; - initComponents(); + private static final long serialVersionUID = 1L; + private int arrDisplayHeight; + private int arrDisplayWidth; + private int contentWidth; + private int contentHeight; + private AlgVisualizer algVisualizer; + private JPanel arrPanel; + private ArrDisplay arrDisplay; + private JPanel buttonPanel; + private JButton resetButton; + private JButton bubbleButton; + private JButton insertionButton; + private JButton selectionButton; + private JButton mergeButton; + private JButton quickButton; + private JComboBox sizeChanger; + private JSlider FPSslider; + private JLabel performanceLabel; + + public ContentWindow(AlgVisualizer algVisualizer) { + super("Algorithm Visualizer"); // Set the name of the frame + this.algVisualizer = algVisualizer; + initComponents(); setFrame(); - } + } - /* + /* * Initializes all of the components that will be in this frame. Add the action * change listeners and set their colors. - */ - public void initComponents() { - - double screenHeight = Toolkit.getDefaultToolkit().getScreenSize().getHeight(); - String[] sizeOptions; - - if (screenHeight > 1080.0) { // 4k - arrDisplayHeight = 2000; - contentWidth = arrDisplayHeight; - sizeOptions = new String[] { "10", "50", "100", "250", "500", "1000" }; - } else if (screenHeight < 1080.0) { // too small for original dimensions - arrDisplayHeight = 500; - contentWidth = arrDisplayHeight + 500; - sizeOptions = new String[] { "10", "50", "100", "250", "500" }; - } else { // Original dimensions (1080p) - arrDisplayHeight = 900; - contentWidth = arrDisplayHeight + 20; - sizeOptions = new String[] { "10", "50", "100", "300", "450", "900" }; - } - - contentHeight = arrDisplayHeight + 110; - arrDisplayWidth = arrDisplayHeight; - algVisualizer.setSizeOptions(sizeOptions); - - arrDisplay = new ArrDisplay(algVisualizer, this); - arrDisplay.setArr(algVisualizer.getArr()); - arrDisplay.setPreferredSize(new Dimension(arrDisplayWidth, arrDisplayHeight)); - - // Panels in the frame that will hold all components. - // JPanels use the flowLayout to manage their components automatically. - buttonPanel = new JPanel(); - buttonPanel.setBackground(Color.DARK_GRAY); - - arrPanel = new JPanel(); - arrPanel.setLayout(new GridBagLayout()); - arrPanel.setBackground(Color.DARK_GRAY); - arrPanel.add(arrDisplay); - - // Initialize all components and add action listeners - + */ + public void initComponents() { + double screenHeight = Toolkit.getDefaultToolkit().getScreenSize().getHeight(); + String[] sizeOptions; + + if (screenHeight > 1080.0) { // 4k + arrDisplayHeight = 2000; + contentWidth = arrDisplayHeight; + sizeOptions = new String[]{"10", "50", "100", "250", "500", "1000"}; + } else if (screenHeight < 1080.0) { // too small for original dimensions + arrDisplayHeight = 500; + contentWidth = arrDisplayHeight + 500; + sizeOptions = new String[]{"10", "50", "100", "250", "500"}; + } else { // Original dimensions (1080p) + arrDisplayHeight = 900; + contentWidth = arrDisplayHeight + 100; + sizeOptions = new String[]{"10", "50", "100", "300", "450", "900"}; + } + + contentHeight = arrDisplayHeight + 110; + arrDisplayWidth = arrDisplayHeight; + algVisualizer.setSizeOptions(sizeOptions); + + arrDisplay = new ArrDisplay(algVisualizer, this); + arrDisplay.setArr(algVisualizer.getArr()); + arrDisplay.setPreferredSize(new Dimension(arrDisplayWidth, arrDisplayHeight)); + + // Panels in the frame that will hold all components. + // JPanels use the flowLayout to manage their components automatically. + buttonPanel = new JPanel(); + buttonPanel.setBackground(Color.DARK_GRAY); + + arrPanel = new JPanel(); + arrPanel.setLayout(new GridBagLayout()); + arrPanel.setBackground(Color.DARK_GRAY); + arrPanel.add(arrDisplay); + + // Initialize all components and add action listeners initJButtons(); sizeChanger = new JComboBox(algVisualizer.getSizeOptions()); // Pass the String containing all of the - // size options - sizeChanger.addActionListener(algVisualizer); - sizeChanger.setBackground(Color.WHITE); - - FPSslider = new JSlider(JSlider.HORIZONTAL, algVisualizer.getMinFPS(), algVisualizer.getMaxFPS(), - algVisualizer.getInitFPS()); - FPSslider.addChangeListener(algVisualizer); - FPSslider.setBackground(Color.DARK_GRAY); - //FPSslider.setPreferredSize(new Dimension(75,25)); - - performanceLabel = new JLabel(); - performanceLabel.setHorizontalAlignment(SwingConstants.CENTER); - } + sizeChanger.addActionListener(algVisualizer); + sizeChanger.setBackground(Color.WHITE); + + FPSslider = new JSlider(JSlider.HORIZONTAL, algVisualizer.getMinFPS(), algVisualizer.getMaxFPS(), + algVisualizer.getInitFPS()); + FPSslider.addChangeListener(algVisualizer); + FPSslider.setBackground(Color.DARK_GRAY); + + performanceLabel = new JLabel(); + performanceLabel.setHorizontalAlignment(SwingConstants.CENTER); + } // initialize the buttons for the frame private void initJButtons() { @@ -112,91 +108,90 @@ private JButton initJButton(String buttonName) { return newButton; } - /* + /* * Sets up the frame and adds all of the components to this frame - */ - public void setFrame() { // Add JButtons / components to button panel - buttonPanel.add(resetButton); - buttonPanel.add(bubbleButton); - buttonPanel.add(selectionButton); - buttonPanel.add(insertionButton); - buttonPanel.add(mergeButton); - buttonPanel.add(quickButton); - buttonPanel.add(sizeChanger); - buttonPanel.add(FPSslider); - // Initialize and make the frame visible - setPreferredSize(new Dimension(contentWidth, contentHeight)); // 105 is the height of the performance label and - // the button panel - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - setResizable(false); // Cannot be resizable, causes visual issues - add(buttonPanel, BorderLayout.PAGE_START); // Button panel added to the top of the frame - add(arrPanel, BorderLayout.PAGE_END); // Array display is added to the bottom of the frame - add(performanceLabel); - pack(); - setLocationRelativeTo(null); // center of the screen - setVisible(true); - } - - // Set the availability of the sorting buttons - public void setSortButtons(boolean toSet) { - bubbleButton.setEnabled(toSet); - selectionButton.setEnabled(toSet); - insertionButton.setEnabled(toSet); - mergeButton.setEnabled(toSet); - quickButton.setEnabled(toSet); - } - - public JLabel getPerformanceLabel() { - return performanceLabel; - } - - public ArrDisplay getArrDisplay() { - return arrDisplay; - } - - public int getContentWidth() { - return contentWidth; - } - - public int getContentHeight() { - return contentHeight; - } - - public int getArrDisplayWidth() { - return arrDisplayWidth; - } - - public int getArrDisplayHeight() { - return arrDisplayHeight; - } - - - public JButton getBubbleButton() { - return bubbleButton; - } - - public JButton getSelectionButton() { - return selectionButton; - } - - public JButton getInsertionButton() { - return insertionButton; - } - - public JButton getMergeButton() { - return mergeButton; - } - - public JButton getQuickButton() { - return quickButton; - } - - public JButton getResetButton() { - return resetButton; - } - - public JComboBox getSizeChanger() { - return sizeChanger; - } + */ + public void setFrame() { // Add JButtons / components to button panel + buttonPanel.add(resetButton); + buttonPanel.add(bubbleButton); + buttonPanel.add(selectionButton); + buttonPanel.add(insertionButton); + buttonPanel.add(mergeButton); + buttonPanel.add(quickButton); + buttonPanel.add(sizeChanger); + buttonPanel.add(FPSslider); + // Initialize and make the frame visible + setPreferredSize(new Dimension(contentWidth, contentHeight)); // 105 is the height of the performance label and + // the button panel + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setResizable(false); // Cannot be resizable, causes visual issues + add(buttonPanel, BorderLayout.PAGE_START); // Button panel added to the top of the frame + add(arrPanel, BorderLayout.PAGE_END); // Array display is added to the bottom of the frame + add(performanceLabel); + pack(); + setLocationRelativeTo(null); // center of the screen + setVisible(true); + } + + // Set the availability of the sorting buttons + public void setSortButtons(boolean toSet) { + bubbleButton.setEnabled(toSet); + selectionButton.setEnabled(toSet); + insertionButton.setEnabled(toSet); + mergeButton.setEnabled(toSet); + quickButton.setEnabled(toSet); + } + + public JLabel getPerformanceLabel() { + return performanceLabel; + } + + public ArrDisplay getArrDisplay() { + return arrDisplay; + } + + public int getContentWidth() { + return contentWidth; + } + + public int getContentHeight() { + return contentHeight; + } + + public int getArrDisplayWidth() { + return arrDisplayWidth; + } + + public int getArrDisplayHeight() { + return arrDisplayHeight; + } + + public JButton getBubbleButton() { + return bubbleButton; + } + + public JButton getSelectionButton() { + return selectionButton; + } + + public JButton getInsertionButton() { + return insertionButton; + } + + public JButton getMergeButton() { + return mergeButton; + } + + public JButton getQuickButton() { + return quickButton; + } + + public JButton getResetButton() { + return resetButton; + } + + public JComboBox getSizeChanger() { + return sizeChanger; + } }