<commit_before>package com.puzzletimer;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.UUID;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;

import net.miginfocom.swing.MigLayout;

import com.puzzletimer.models.Category;
import com.puzzletimer.models.Scramble;
import com.puzzletimer.parsers.ScrambleParser;
import com.puzzletimer.parsers.ScrambleParserBuilder;
import com.puzzletimer.scramblers.Scrambler;
import com.puzzletimer.scramblers.ScramblerBuilder;
import com.puzzletimer.state.CategoryListener;
import com.puzzletimer.state.CategoryManager;
import com.puzzletimer.state.ScrambleListener;
import com.puzzletimer.state.ScrambleManager;

@SuppressWarnings("serial")
public class ScrambleQueueFrame extends JFrame {
    private JTable table;
    private JButton buttonUp;
    private JButton buttonDown;
    private JButton buttonRemove;
    private JButton buttonImportFromFile;
    private JButton buttonExport;
    private JComboBox comboBoxScrambler;
    private JSpinner spinnerNumberOfScrambles;
    private JButton buttonImportFromScrambler;
    private JButton buttonOk;

    public ScrambleQueueFrame(final CategoryManager categoryManager, final ScrambleManager scrambleManager) {
        super();

        setMinimumSize(new Dimension(640, 480));
        setPreferredSize(getMinimumSize());

        createComponents();

        // on category change
        categoryManager.addCategoryListener(new CategoryListener() {
            @Override
            public void categoriesUpdated(Category[] categories, Category currentCategory) {
                // title
                setTitle("Scramble Queue - " + currentCategory.description);

                // scrambler combobox
                ScrambleQueueFrame.this.comboBoxScrambler.removeAllItems();

                Scrambler currentScrambler = ScramblerBuilder.getScrambler(
                    categoryManager.getCurrentCategory().scramblerId);
                String puzzleId = currentScrambler.getScramblerInfo().getPuzzleId();

                for (Scrambler scrambler : ScramblerBuilder.getScramblers()) {
                    if (scrambler.getScramblerInfo().getPuzzleId().equals(puzzleId)) {
                        ScrambleQueueFrame.this.comboBoxScrambler.addItem(scrambler);
                    }
                }
            }
        });
        categoryManager.notifyListeners();

        // on queue update
        scrambleManager.addScrambleListener(new ScrambleListener() {
            @Override
            public void scrambleQueueUpdated(Scramble[] queue) {
                updateTable(queue);
                updateButtons(ScrambleQueueFrame.this.table);
            }
        });

        // enable/disable buttons
        this.table.getSelectionModel().addListSelectionListener(
            new ListSelectionListener() {
                @Override
                public void valueChanged(ListSelectionEvent event) {
                    updateButtons(ScrambleQueueFrame.this.table);
                }
            });

        // up button
        this.buttonUp.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                JTable table = ScrambleQueueFrame.this.table;
                int[] selectedRows = table.getSelectedRows();

                // move scrambles
                scrambleManager.moveScramblesUp(selectedRows);

                // fix selection
                table.removeRowSelectionInterval(0, selectedRows.length - 1);
                for (int selectedRow : selectedRows) {
                    table.addRowSelectionInterval(selectedRow - 1, selectedRow - 1);
                }
            }
        });

        // down button
        this.buttonDown.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                JTable table = ScrambleQueueFrame.this.table;
                int[] selectedRows = table.getSelectedRows();

                // move scrambles
                scrambleManager.moveScramblesDown(selectedRows);

                // fix selection
                table.removeRowSelectionInterval(0, selectedRows.length - 1);
                for (int selectedRow : selectedRows) {
                    table.addRowSelectionInterval(selectedRow + 1, selectedRow + 1);
                }
            }
        });

        // remove button
        this.buttonRemove.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                scrambleManager.removeScrambles(
                    ScrambleQueueFrame.this.table.getSelectedRows());
            }
        });

        // import from file
        this.buttonImportFromFile.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                JFileChooser fileChooser = new JFileChooser();
                int action = fileChooser.showOpenDialog(ScrambleQueueFrame.this);
                if (action != JFileChooser.APPROVE_OPTION) {
                    return;
                }

                Category category = categoryManager.getCurrentCategory();
                Scrambler scrambler = ScramblerBuilder.getScrambler(category.scramblerId);
                String puzzleId = scrambler.getScramblerInfo().getPuzzleId();
                ScrambleParser scrambleParser = ScrambleParserBuilder.getScrambleParser(puzzleId);

                Scramble[] scrambles;
                try {
                    scrambles = loadScramblesFromFile(
                        fileChooser.getSelectedFile(),
                        scrambleParser);
                } catch (IOException e) {
                    JOptionPane.showMessageDialog(
                        ScrambleQueueFrame.this,
                        "Error opening file \"" + fileChooser.getSelectedFile().getAbsolutePath() + "\".",
                        "Error",
                        JOptionPane.ERROR_MESSAGE);
                    return;
                }

                scrambleManager.addScrambles(scrambles);
            }
        });

        // export to file
        this.buttonExport.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                JFileChooser fileChooser = new JFileChooser();
                int action = fileChooser.showSaveDialog(ScrambleQueueFrame.this);
                if (action != JFileChooser.APPROVE_OPTION) {
                    return;
                }
<commit_msg>File selection dialog adjustments<commit_after>package com.puzzletimer;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.UUID;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;

import net.miginfocom.swing.MigLayout;

import com.puzzletimer.models.Category;
import com.puzzletimer.models.Scramble;
import com.puzzletimer.parsers.ScrambleParser;
import com.puzzletimer.parsers.ScrambleParserBuilder;
import com.puzzletimer.scramblers.Scrambler;
import com.puzzletimer.scramblers.ScramblerBuilder;
import com.puzzletimer.state.CategoryListener;
import com.puzzletimer.state.CategoryManager;
import com.puzzletimer.state.ScrambleListener;
import com.puzzletimer.state.ScrambleManager;

@SuppressWarnings("serial")
public class ScrambleQueueFrame extends JFrame {
    private JTable table;
    private JButton buttonUp;
    private JButton buttonDown;
    private JButton buttonRemove;
    private JButton buttonImportFromFile;
    private JButton buttonExport;
    private JComboBox comboBoxScrambler;
    private JSpinner spinnerNumberOfScrambles;
    private JButton buttonImportFromScrambler;
    private JButton buttonOk;

    public ScrambleQueueFrame(final CategoryManager categoryManager, final ScrambleManager scrambleManager) {
        super();

        setMinimumSize(new Dimension(640, 480));
        setPreferredSize(getMinimumSize());

        createComponents();

        // on category change
        categoryManager.addCategoryListener(new CategoryListener() {
            @Override
            public void categoriesUpdated(Category[] categories, Category currentCategory) {
                // title
                setTitle("Scramble Queue - " + currentCategory.description);

                // scrambler combobox
                ScrambleQueueFrame.this.comboBoxScrambler.removeAllItems();

                Scrambler currentScrambler = ScramblerBuilder.getScrambler(
                    categoryManager.getCurrentCategory().scramblerId);
                String puzzleId = currentScrambler.getScramblerInfo().getPuzzleId();

                for (Scrambler scrambler : ScramblerBuilder.getScramblers()) {
                    if (scrambler.getScramblerInfo().getPuzzleId().equals(puzzleId)) {
                        ScrambleQueueFrame.this.comboBoxScrambler.addItem(scrambler);
                    }
                }
            }
        });
        categoryManager.notifyListeners();

        // on queue update
        scrambleManager.addScrambleListener(new ScrambleListener() {
            @Override
            public void scrambleQueueUpdated(Scramble[] queue) {
                updateTable(queue);
                updateButtons(ScrambleQueueFrame.this.table);
            }
        });

        // enable/disable buttons
        this.table.getSelectionModel().addListSelectionListener(
            new ListSelectionListener() {
                @Override
                public void valueChanged(ListSelectionEvent event) {
                    updateButtons(ScrambleQueueFrame.this.table);
                }
            });

        // up button
        this.buttonUp.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                JTable table = ScrambleQueueFrame.this.table;
                int[] selectedRows = table.getSelectedRows();

                // move scrambles
                scrambleManager.moveScramblesUp(selectedRows);

                // fix selection
                table.removeRowSelectionInterval(0, selectedRows.length - 1);
                for (int selectedRow : selectedRows) {
                    table.addRowSelectionInterval(selectedRow - 1, selectedRow - 1);
                }
            }
        });

        // down button
        this.buttonDown.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                JTable table = ScrambleQueueFrame.this.table;
                int[] selectedRows = table.getSelectedRows();

                // move scrambles
                scrambleManager.moveScramblesDown(selectedRows);

                // fix selection
                table.removeRowSelectionInterval(0, selectedRows.length - 1);
                for (int selectedRow : selectedRows) {
                    table.addRowSelectionInterval(selectedRow + 1, selectedRow + 1);
                }
            }
        });

        // remove button
        this.buttonRemove.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                scrambleManager.removeScrambles(
                    ScrambleQueueFrame.this.table.getSelectedRows());
            }
        });

        // import from file
        this.buttonImportFromFile.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                JFileChooser fileChooser = new JFileChooser();
                fileChooser.setFileFilter(new FileNameExtensionFilter("Scramble files (*.txt)", "txt"));
                int action = fileChooser.showOpenDialog(ScrambleQueueFrame.this);
                if (action != JFileChooser.APPROVE_OPTION) {
                    return;
                }

                Category category = categoryManager.getCurrentCategory();
                Scrambler scrambler = ScramblerBuilder.getScrambler(category.scramblerId);
                String puzzleId = scrambler.getScramblerInfo().getPuzzleId();
                ScrambleParser scrambleParser = ScrambleParserBuilder.getScrambleParser(puzzleId);

                Scramble[] scrambles;
                try {
                    scrambles = loadScramblesFromFile(
                        fileChooser.getSelectedFile(),
                        scrambleParser);
                } catch (IOException e) {
                    JOptionPane.showMessageDialog(
                        ScrambleQueueFrame.this,
                        "Error opening file \"" + fileChooser.getSelectedFile().getAbsolutePath() + "\".",
                        "Error",
                        JOptionPane.ERROR_MESSAGE);
                    return;
                }

                scrambleManager.addScrambles(scrambles);
            }
        });

        // export to file
        this.buttonExport.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                JFileChooser fileChooser = new JFileChooser();
                fileChooser.setSelectedFile(new File("scrambles.txt"));
                fileChooser.setFileFilter(new FileNameExtensionFilter("Scramble files (*.txt)", "txt"));
                int action = fileChooser.showSaveDialog(ScrambleQueueFrame.this);
                if (action != JFileChooser.APPROVE_OPTION) {
                    return;
                }

{'fraction_non_alphanumeric': 0.07955444239388347, 'fraction_numerical': 0.0018455048774057474, 'mean_word_length': 2.1842602308499477, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1204714', 'n_tokens_mistral': 4020, 'n_tokens_neox': 3752, 'n_words': 683}