// Set the buttons displayed in the panel
  // textFilePath - The path to the sound effect definition file
  // Returns 0 (an error occurred and a new project was opened), 1 (an error occurred), 2 (the
  // project opened normally)
  public int loadFile(String textFilePath) {
    clearBoard();

    // Get the sounds contained in the given project file
    ArrayList<SoundInfo> readSounds = soundManager.readFile(textFilePath);

    // Add buttons to the interface for each sound in the file
    for (int s = 0; s < readSounds.size(); s++) {
      SoundInfo curr = readSounds.get(s);
      if (checkValidKey(curr.getKeyName())) {
        addSound(readSounds.get(s));
      } else {
        soundManager.deleteSound(curr.getKeyCode());
      }
    }

    // Report if an error occurred while opening the project
    // Allow the user to close the project without proceeding
    if (soundManager.getProjectModified()) {
      int choice =
          JOptionPane.showConfirmDialog(
              frame,
              "One or more errors were encountered while reading the project file. "
                  + "The file may be missing, not well-formatted, or not a Cue Masher project file. Do you want to proceed?",
              "Keep Project Open?",
              JOptionPane.YES_NO_OPTION);
      if (choice == JOptionPane.NO_OPTION) {
        openNewProject();
        return 0;
      }
      return 1;
    }
    return 2;
  }
  // Update a sound in the displayed buttons, sound list, and sound file
  // soundClip - An object storing information about the added or updated sound
  public void updateSound(SoundInfo soundClip) {

    // Add the sound to the project
    SoundInfo newSound = soundManager.addSound(soundClip);

    if (newSound != null) {
      // Add a new button to the GUI
      addSound(newSound);
    }

    if (soundManager.getProjectModified()) {

      if (newSound == null) {
        // An existing sound was updated
        // Update the button label and tooltip
        for (int s = 0; s < soundList.size(); s++) {
          BoardButton button = soundList.get(s);
          if (button.getKeyCode() == soundClip.getKeyCode()) {
            button.updateButtonText();
            break;
          }
        }
      }

      // Update the GUI
      frame.setProjectModified();
      refreshSoundBoard();
    }
  }
  // Clears all the buttons from the GUI
  private void clearBoard() {

    // Remove all the old buttons and refresh the panel
    for (int i = 0; i < soundList.size(); i++) {
      BoardButton curr = soundList.get(i);
      remove(curr.getButton());
    }
    refreshSoundBoard();

    // Refresh the list of sound board buttons
    soundList = new ArrayList<BoardButton>();
  }
  // Add a button to the GUI for a sound
  // soundInfo - The sound to add to the GUI
  private void addSound(SoundInfo soundInfo) {

    // Create a button for the sound
    SoundButton buttonContainer = new SoundButton(dialogManager, soundInfo);

    // Add the new sound button to the list of buttons and the panel
    soundList.add(buttonContainer);
    add(buttonContainer.getButton());
  }
  // Removes a sound from the interface and sound list
  // keyCode - The keyboard key code associated with the sound
  public void deleteSound(int keyCode) {
    soundManager.deleteSound(keyCode);

    // Search the sound buttons for the button to remove
    for (int s = 0; s < soundList.size(); s++) {
      BoardButton button = soundList.get(s);
      if (button.getKeyCode() == keyCode) {
        // Remove the button from the interface
        remove(button.getButton());
        soundList.remove(s);

        // Update the GUI
        frame.setProjectModified();
        refreshSoundBoard();

        break;
      }
    }
  }
  // Set the positions and sizes of the buttons and display the panel
  public void paintComponent(Graphics page) {
    super.paintComponent(page);

    // Calculate the button width and height so the buttons span the screen
    int screenWidth = getWidth();
    int screenHeight = getHeight();
    int[] buttonWidth = new int[5];
    buttonWidth[0] = (screenWidth - (BUTTON_SPACE * 13)) / 13;
    buttonWidth[1] = buttonWidth[0];
    buttonWidth[2] = (screenWidth - (BUTTON_SPACE * 11)) / 11;
    buttonWidth[3] = (screenWidth - (BUTTON_SPACE * 11)) / 10;
    buttonWidth[4] = (screenWidth - (BUTTON_SPACE * 11)) / 10;
    int buttonHeight = (screenHeight - (BUTTON_SPACE * 7)) / 6;

    int xPos;
    int yPos;
    // Subtract 1 from this int every time a sound button is placed where it belongs
    // When it equals zero all sounds have been placed
    int keysToMap = soundList.size();
    ArrayList<BoardButton> copy = (ArrayList<BoardButton>) soundList.clone();

    // For each string in the rows array, check if any of the key strings for the sound match
    for (int j = 0; j < rows.length; j++) {
      int i = 0;

      // For each string in the rows array, check each sound object to see if it is played with a
      // key in that row
      while ((copy.size() > 0) && (i < soundList.size())) {
        int index = 0;
        if (soundList.get(i).getKeyName().indexOf("N") != -1) {
          if (j == 4) index = rows[j].indexOf(soundList.get(i).getKeyName().substring(1));
          else index = -1;
        } else {
          if (j != 4)
            // Get where the key string is in the rows array
            index = rows[j].indexOf(soundList.get(i).getKeyName());
          else index = -1;
        }
        // If the key string doesn't exist, the key is not in this row and the button won't be
        // placed
        if (index != -1) {
          // Place the button based on the corresponding key's position on the keyboard
          xPos = ((buttonWidth[j] + BUTTON_SPACE) * index) + BUTTON_SPACE;
          yPos = ((buttonHeight + BUTTON_SPACE) * j) + BUTTON_SPACE;

          JButton curr = soundList.get(i).getButton();
          // Set the button's size and position to the size and position calculated
          curr.setSize(new Dimension(buttonWidth[j], buttonHeight));
          curr.setLocation(xPos, yPos);
          // Decrement the number of sounds left to map
          copy.remove(soundList.get(i));
          keysToMap -= 1;
        }

        // Increment the index of the sound to check
        i++;
      }
    }

    // Set the x-position, y-position, and size of the spacebar key
    // It will span the bottom of the screen and be the same height as the other buttons
    JButton btnSpace = space.getButton();
    xPos = 10;
    yPos = ((buttonHeight + BUTTON_SPACE) * 5) + BUTTON_SPACE;
    btnSpace.setSize(new Dimension(screenWidth - (BUTTON_SPACE * 2), buttonHeight));
    btnSpace.setLocation(xPos, yPos);
  }