PresentationLayer.CreatePuzzleJFrame.java Source code

Java tutorial

Introduction

Here is the source code for PresentationLayer.CreatePuzzleJFrame.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package PresentationLayer;

import BusinessLogic.Controller;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfTemplate;
import com.lowagie.text.pdf.PdfWriter;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSpinner.DefaultEditor;
import javax.swing.JTable;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;

/**
 *
 * @author hasaan
 */
public class CreatePuzzleJFrame extends javax.swing.JFrame {

    /**
     * Creates new form CreatePuzzleJFrame
     */
    private final float PIXELS_IN_ONE_INCH = 72.015f;
    private float docWidth;
    private float docHeight;

    private int gridSize;
    private int boxSize;
    private Character[][] puzzleGrid;
    private LinkedHashMap<String, String> acrossAnsClueHM = null;
    private LinkedHashMap<String, String> downAnsClueHM = null;

    public CreatePuzzleJFrame() {
        //create table model

        initComponents();
        Dimension d = new Dimension(915, 800);
        this.setMinimumSize(d);
        this.setSize(d);
        HelpfulStaticFunctions.locateAtCentre(this);

        //make jSpinners non-editable
        //        ((DefaultEditor) boxSizejSpinner.getEditor()).getTextField().setEditable(false);
        //        ((DefaultEditor) gridSizejSpinner.getEditor()).getTextField().setEditable(false);
        //        ((DefaultEditor) densityjSpinner.getEditor()).getTextField().setEditable(false);

        puzzlejTable.setGridColor(Color.BLACK);
        gridSize = (int) gridSizejSpinner.getValue();
        puzzlejTable.setModel(new javax.swing.table.DefaultTableModel(gridSize, gridSize));

        DefaultTableModel m = (DefaultTableModel) puzzlejTable.getModel();

        boxSizejSpinnerStateChanged(null);
        //initialize docWidth & docHeight
        updateDocSizeFromSpinners();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        fileChooser = new javax.swing.JFileChooser();
        fileChooser1 = new javax.swing.JFileChooser();
        controlsjPanel = new javax.swing.JPanel();
        gridSizejSpinner = new javax.swing.JSpinner();
        gridSizejLabel = new javax.swing.JLabel();
        boxSizejLabel = new javax.swing.JLabel();
        boxSizejSpinner = new javax.swing.JSpinner();
        settingsjButton = new javax.swing.JButton();
        fileNameLabel = new javax.swing.JLabel();
        boxSizejLabel1 = new javax.swing.JLabel();
        gridSizejLabel3 = new javax.swing.JLabel();
        densityjSpinner = new javax.swing.JSpinner();
        titlejLabel = new javax.swing.JLabel();
        settingsjButton1 = new javax.swing.JButton();
        footjPanel = new javax.swing.JPanel();
        generatePuzzlejButton = new javax.swing.JButton();
        savePuzzlejButton = new javax.swing.JButton();
        showAnswersjCheckBox = new javax.swing.JCheckBox();
        gridSizejLabel1 = new javax.swing.JLabel();
        documentHeightjSpinner = new javax.swing.JSpinner();
        documentWidthjSpinner = new javax.swing.JSpinner();
        gridSizejLabel2 = new javax.swing.JLabel();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        middlejPanel = new javax.swing.JPanel();
        mainjScrollPane = new javax.swing.JScrollPane();
        printablejPanel = new javax.swing.JPanel();
        mainjSplitPane = new javax.swing.JSplitPane();
        puzzlejPanel = new javax.swing.JPanel();
        puzzlejScrollPane = new javax.swing.JScrollPane();
        puzzlejTable = new javax.swing.JTable();
        cluesjPanel = new javax.swing.JPanel();
        cluesjSplitPane = new javax.swing.JSplitPane();
        jScrollPane1 = new javax.swing.JScrollPane();
        acrossCluesjTextArea = new javax.swing.JTextArea();
        jScrollPane2 = new javax.swing.JScrollPane();
        downCluesjTextArea = new javax.swing.JTextArea();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Crossword Puzzle Creator");

        controlsjPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        gridSizejSpinner.setModel(new javax.swing.SpinnerNumberModel(50, 5, 500, 1));
        gridSizejSpinner.setToolTipText("5 - 500");
        gridSizejSpinner.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                gridSizejSpinnerStateChanged(evt);
            }
        });

        gridSizejLabel.setFont(new java.awt.Font("Lucida Grande", 0, 14)); // NOI18N
        gridSizejLabel.setText("Grid Size:");
        gridSizejLabel.setToolTipText("");

        boxSizejLabel.setFont(new java.awt.Font("Lucida Grande", 0, 14)); // NOI18N
        boxSizejLabel.setText("Box Size:");

        boxSizejSpinner.setModel(new javax.swing.SpinnerNumberModel(10, 10, 90, 1));
        boxSizejSpinner.setToolTipText("10 - 90");
        boxSizejSpinner.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                boxSizejSpinnerStateChanged(evt);
            }
        });

        settingsjButton.setText("Change");
        settingsjButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                settingsjButtonActionPerformed(evt);
            }
        });

        fileNameLabel.setText("<Not Selected>");
        fileNameLabel.setToolTipText("See \"About\" section");

        boxSizejLabel1.setFont(new java.awt.Font("Lucida Grande", 0, 14)); // NOI18N
        boxSizejLabel1.setText("Data Source:");
        boxSizejLabel1.setToolTipText("See \"About\" section");

        gridSizejLabel3.setFont(new java.awt.Font("Lucida Grande", 0, 14)); // NOI18N
        gridSizejLabel3.setLabelFor(densityjSpinner);
        gridSizejLabel3.setText("Puzzle Density:");
        gridSizejLabel3.setToolTipText("Higher the value, denser the puzzle");

        densityjSpinner.setModel(new javax.swing.SpinnerNumberModel(10, 1, 30, 1));
        densityjSpinner.setToolTipText("1 - 30");

        titlejLabel.setBackground(new java.awt.Color(204, 204, 204));
        titlejLabel.setFont(new java.awt.Font("Luminari", 0, 36)); // NOI18N
        titlejLabel.setForeground(new java.awt.Color(204, 0, 0));
        titlejLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        titlejLabel.setText("Crossword Puzzle Creator");
        titlejLabel.setToolTipText("");

        settingsjButton1.setText("About");
        settingsjButton1.setNextFocusableComponent(savePuzzlejButton);
        settingsjButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                settingsjButton1ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout controlsjPanelLayout = new javax.swing.GroupLayout(controlsjPanel);
        controlsjPanel.setLayout(controlsjPanelLayout);
        controlsjPanelLayout.setHorizontalGroup(
                controlsjPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(controlsjPanelLayout.createSequentialGroup()
                                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(titlejLabel)
                                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addGroup(controlsjPanelLayout.createSequentialGroup().addContainerGap()
                                .addComponent(gridSizejLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(gridSizejSpinner, javax.swing.GroupLayout.PREFERRED_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(18, 18, 18).addComponent(boxSizejLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(boxSizejSpinner, javax.swing.GroupLayout.PREFERRED_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(18, 18, 18).addComponent(gridSizejLabel3)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(densityjSpinner, javax.swing.GroupLayout.PREFERRED_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(18, 18, 18).addComponent(boxSizejLabel1)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(fileNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 99,
                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(settingsjButton).addGap(18, 18, 18)
                                .addComponent(settingsjButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 70,
                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addContainerGap()));
        controlsjPanelLayout.setVerticalGroup(
                controlsjPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(controlsjPanelLayout.createSequentialGroup().addComponent(titlejLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addGroup(controlsjPanelLayout
                                        .createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                        .addComponent(gridSizejSpinner, javax.swing.GroupLayout.PREFERRED_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addComponent(gridSizejLabel)
                                        .addComponent(boxSizejSpinner, javax.swing.GroupLayout.PREFERRED_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addComponent(boxSizejLabel)
                                        .addComponent(settingsjButton, javax.swing.GroupLayout.PREFERRED_SIZE, 40,
                                                javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addComponent(boxSizejLabel1).addComponent(gridSizejLabel3)
                                        .addComponent(densityjSpinner, javax.swing.GroupLayout.PREFERRED_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addComponent(settingsjButton1, javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addComponent(fileNameLabel, javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))));

        footjPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        generatePuzzlejButton.setText("Generate");
        generatePuzzlejButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                generatePuzzlejButtonActionPerformed(evt);
            }
        });

        savePuzzlejButton.setText("Save");
        savePuzzlejButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                savePuzzlejButtonActionPerformed(evt);
            }
        });

        showAnswersjCheckBox.setText(" Show Answers");
        showAnswersjCheckBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                showAnswersjCheckBoxActionPerformed(evt);
            }
        });

        gridSizejLabel1.setFont(new java.awt.Font("Lucida Grande", 0, 14)); // NOI18N
        gridSizejLabel1.setText("Width:");

        documentHeightjSpinner.setModel(new javax.swing.SpinnerNumberModel(Float.valueOf(11.692f),
                Float.valueOf(5.0f), Float.valueOf(100.0f), Float.valueOf(1.0f)));
        documentHeightjSpinner.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                documentHeightjSpinnerStateChanged(evt);
            }
        });

        documentWidthjSpinner.setModel(new javax.swing.SpinnerNumberModel(Float.valueOf(8.262f),
                Float.valueOf(5.0f), Float.valueOf(100.0f), Float.valueOf(1.0f)));
        documentWidthjSpinner.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                documentWidthjSpinnerStateChanged(evt);
            }
        });

        gridSizejLabel2.setFont(new java.awt.Font("Lucida Grande", 0, 14)); // NOI18N
        gridSizejLabel2.setText("Height (in):");

        jLabel1.setText("in");

        jLabel2.setText("in");

        javax.swing.GroupLayout footjPanelLayout = new javax.swing.GroupLayout(footjPanel);
        footjPanel.setLayout(footjPanelLayout);
        footjPanelLayout.setHorizontalGroup(footjPanelLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(footjPanelLayout.createSequentialGroup().addGap(29, 29, 29)
                        .addComponent(savePuzzlejButton, javax.swing.GroupLayout.PREFERRED_SIZE, 103,
                                javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18).addComponent(generatePuzzlejButton).addGap(50, 50, 50)
                        .addComponent(gridSizejLabel1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(documentWidthjSpinner, javax.swing.GroupLayout.DEFAULT_SIZE, 80,
                                Short.MAX_VALUE)
                        .addGap(2, 2, 2).addComponent(jLabel1).addGap(18, 18, 18).addComponent(gridSizejLabel2)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(documentHeightjSpinner, javax.swing.GroupLayout.DEFAULT_SIZE, 80,
                                Short.MAX_VALUE)
                        .addGap(2, 2, 2).addComponent(jLabel2)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(showAnswersjCheckBox).addGap(68, 68, 68)));
        footjPanelLayout.setVerticalGroup(footjPanelLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(savePuzzlejButton, javax.swing.GroupLayout.Alignment.TRAILING,
                        javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, footjPanelLayout
                        .createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(generatePuzzlejButton, javax.swing.GroupLayout.PREFERRED_SIZE, 42,
                                javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(showAnswersjCheckBox).addComponent(gridSizejLabel2)
                        .addComponent(documentHeightjSpinner, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(documentWidthjSpinner, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(gridSizejLabel1).addComponent(jLabel1).addComponent(jLabel2)));

        mainjScrollPane.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Printable Puzzle Preview",
                javax.swing.border.TitledBorder.CENTER, javax.swing.border.TitledBorder.DEFAULT_POSITION));
        mainjScrollPane.setPreferredSize(new java.awt.Dimension(600, 600));

        printablejPanel.setAutoscrolls(true);
        printablejPanel.setPreferredSize(new java.awt.Dimension(595, 842));
        printablejPanel.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                printablejPanelMouseDragged(evt);
            }
        });
        printablejPanel.setLayout(new javax.swing.BoxLayout(printablejPanel, javax.swing.BoxLayout.LINE_AXIS));

        mainjSplitPane.setBorder(null);
        mainjSplitPane.setDividerLocation(595);
        mainjSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        mainjSplitPane.setResizeWeight(0.5);
        mainjSplitPane.setFocusable(false);
        mainjSplitPane.setName(""); // NOI18N
        mainjSplitPane.setOpaque(false);
        mainjSplitPane.setRequestFocusEnabled(false);
        mainjSplitPane.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                mainjSplitPaneMouseDragged(evt);
            }
        });
        mainjSplitPane.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                mainjSplitPaneMouseClicked(evt);
            }
        });

        puzzlejPanel.setSize(new java.awt.Dimension(595, 542));
        puzzlejPanel.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                puzzlejPanelMouseDragged(evt);
            }
        });
        puzzlejPanel.setLayout(null);

        puzzlejScrollPane.setAutoscrolls(true);
        puzzlejScrollPane.setEnabled(false);

        puzzlejTable.setModel(new javax.swing.table.DefaultTableModel(new Object[][] {

        }, new String[] {

        }));
        puzzlejTable.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        puzzlejTable.setEnabled(false);
        puzzlejTable.setIntercellSpacing(new java.awt.Dimension(0, 0));
        puzzlejTable.setShowGrid(true);
        puzzlejTable.setTableHeader(null);
        puzzlejTable.setUpdateSelectionOnSort(false);
        puzzlejScrollPane.setViewportView(puzzlejTable);
        puzzlejTable.getAccessibleContext().setAccessibleName("");
        puzzlejTable.getAccessibleContext().setAccessibleDescription("");

        puzzlejPanel.add(puzzlejScrollPane);
        puzzlejScrollPane.setBounds(0, 0, 590, 590);

        mainjSplitPane.setLeftComponent(puzzlejPanel);

        cluesjPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Clues",
                javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
                javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Lucida Grande", 1, 13))); // NOI18N
        cluesjPanel.setAutoscrolls(true);
        cluesjPanel.setLayout(new javax.swing.BoxLayout(cluesjPanel, javax.swing.BoxLayout.LINE_AXIS));

        cluesjSplitPane.setBorder(null);
        cluesjSplitPane.setDividerLocation(300);
        cluesjSplitPane.setResizeWeight(0.5);
        cluesjSplitPane.setToolTipText("Drag to resize across and down clue areas");
        cluesjSplitPane.setAutoscrolls(true);

        jScrollPane1.setBorder(javax.swing.BorderFactory.createTitledBorder(
                new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 1, true), "Across"));
        jScrollPane1.setAutoscrolls(true);

        acrossCluesjTextArea.setEditable(false);
        acrossCluesjTextArea.setBackground(new java.awt.Color(238, 238, 238));
        acrossCluesjTextArea.setColumns(20);
        acrossCluesjTextArea.setRows(5);
        jScrollPane1.setViewportView(acrossCluesjTextArea);

        cluesjSplitPane.setLeftComponent(jScrollPane1);

        jScrollPane2.setBorder(javax.swing.BorderFactory.createTitledBorder(
                new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 1, true), "Downwards"));
        jScrollPane2.setAutoscrolls(true);

        downCluesjTextArea.setEditable(false);
        downCluesjTextArea.setBackground(new java.awt.Color(238, 238, 238));
        downCluesjTextArea.setColumns(20);
        downCluesjTextArea.setLineWrap(true);
        downCluesjTextArea.setRows(5);
        jScrollPane2.setViewportView(downCluesjTextArea);

        cluesjSplitPane.setRightComponent(jScrollPane2);

        cluesjPanel.add(cluesjSplitPane);

        mainjSplitPane.setRightComponent(cluesjPanel);

        printablejPanel.add(mainjSplitPane);

        mainjScrollPane.setViewportView(printablejPanel);

        middlejPanel.add(mainjScrollPane);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(footjPanel, javax.swing.GroupLayout.PREFERRED_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGroup(layout
                                        .createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                        .addComponent(middlejPanel, javax.swing.GroupLayout.Alignment.LEADING,
                                                javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addComponent(controlsjPanel, javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));
        layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup().addGap(10, 10, 10)
                        .addComponent(controlsjPanel, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED,
                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(middlejPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 605,
                                javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED,
                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(footjPanel, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void settingsjButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_settingsjButtonActionPerformed

        File dataFile = createJFileChooser();
        if (dataFile != null) {
            Controller c = Controller.getInstance();
            c.setAndLoadDataSource(dataFile);
            fileNameLabel.setText(dataFile.getName());
        }
    }//GEN-LAST:event_settingsjButtonActionPerformed

    private File createJFileChooser() {
        //        final JFileChooser fileChooser = new JFileChooser();
        //        fileChooser.setDialogType(JFileChooser.OPEN_DIALOG);

        fileChooser1.resetChoosableFileFilters();
        fileChooser1.setAcceptAllFileFilterUsed(false);

        fileChooser1.setDialogTitle("Select Datasource");
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Plain Text files", "txt", "text");
        fileChooser1.setFileFilter(filter);

        if (fileChooser1.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
            return fileChooser1.getSelectedFile();
            //System.out.println(fileChooser.getSelectedFile().toString());
        }
        return null;
    }

    private void generatePuzzlejButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_generatePuzzlejButtonActionPerformed

        Controller controller = Controller.getInstance();
        if (controller.checkIfFileExist() == false) {
            JOptionPane.showMessageDialog(null, "Datasource not found. Kindly select a datasource.",
                    "Datasource not found", JOptionPane.INFORMATION_MESSAGE);
        } else {
            gridSize = (int) gridSizejSpinner.getValue();

            puzzleGrid = new Character[gridSize][gridSize];
            int puzzleDensity = (int) densityjSpinner.getValue();
            acrossAnsClueHM = new LinkedHashMap<String, String>();
            downAnsClueHM = new LinkedHashMap<String, String>();

            showAnswersjCheckBox.setSelected(false);
            controller.generatePuzzle(puzzleGrid, puzzleDensity, acrossAnsClueHM, downAnsClueHM);

            Character[][] grid = new Character[gridSize][gridSize];
            for (int i = 0; i < gridSize; i++) {
                for (int j = 0; j < gridSize; j++) {
                    if (puzzleGrid[i][j] != '.') {
                        grid[i][j] = ' ';
                    } else {
                        grid[i][j] = '.';
                    }

                }
            }

            //set table model
            String[] nulls = new String[puzzleGrid.length];
            DefaultTableModel model = new javax.swing.table.DefaultTableModel(grid, nulls);
            puzzlejTable.setModel(model);
            //
            //              for(int i=0;i<gridSize;i++)
            //              {
            //                  for(int j=0;j<gridSize;j++)
            //                  {
            //                      DefaultTableModel dtm = (DefaultTableModel) puzzlejTable.getModel();
            //                      if(dtm.getValueAt(i, j).toString().matches(".")==true)
            //                      {
            //                         
            //                      }
            //                  }
            //              }
            puzzlejTable.setDefaultRenderer(Object.class, new CustomCellRenderer());

            acrossCluesjTextArea.setText("");
            downCluesjTextArea.setText("");

            for (String key : acrossAnsClueHM.keySet()) {
                String value = acrossAnsClueHM.get(key);
                StringTokenizer strtok = new StringTokenizer(value, "**");
                int position = Integer.parseInt(strtok.nextToken());
                int wordNo = Integer.parseInt(strtok.nextToken());
                String clue = strtok.nextToken();

                acrossCluesjTextArea.append("" + wordNo + ". " + clue + "\n");

                for (int i = 0; i < gridSize; i++) {
                    for (int j = 0; j < gridSize; j++) {
                        if (puzzleGrid[i][j] != '.') {
                            if ((i * gridSize) + j == position) {
                                puzzlejTable.setValueAt(wordNo, i, j);
                            }
                        }
                    }
                } // bring cell number and then display starting point of word in grid

            }
            for (String key : downAnsClueHM.keySet()) {
                String value = downAnsClueHM.get(key);
                StringTokenizer strtok = new StringTokenizer(value, "**");
                int position = Integer.parseInt(strtok.nextToken());
                int wordNo = Integer.parseInt(strtok.nextToken());
                String clue = strtok.nextToken();

                downCluesjTextArea.append(wordNo + ". " + clue + "\n");

                for (int i = 0; i < gridSize; i++) {
                    for (int j = 0; j < gridSize; j++) {
                        if (puzzleGrid[i][j] != '.') {
                            if ((i * gridSize) + j == position) {
                                puzzlejTable.setValueAt(wordNo, i, j);
                            }
                        }
                    }
                }
            }
        }
    }//GEN-LAST:event_generatePuzzlejButtonActionPerformed

    private void updateDocSizeFromSpinners() {
        float inches = (float) documentWidthjSpinner.getValue();
        docWidth = inches * PIXELS_IN_ONE_INCH;
        inches = (float) documentHeightjSpinner.getValue();
        docHeight = inches * PIXELS_IN_ONE_INCH;
    }

    private class CustomCellRenderer extends DefaultTableCellRenderer {

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int column) {
            Component cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

            if (value != null) {
                String cellValue = value.toString();
                //set it so it can display unicode characters
                if (cellValue.compareTo(".") == 0) {
                    //                    System.out.println(cellValue);

                    cell.setFont(new Font("MS Mincho", Font.PLAIN, 5));
                    cell.setBackground(Color.BLACK);

                } else {
                    int fontSize = 12;
                    if (boxSize < 20 && boxSize > 14)
                        fontSize = 10;
                    else if (boxSize < 15)
                        fontSize = boxSize - 2;

                    cell.setFont(new Font("MS Mincho", Font.PLAIN, fontSize));
                    cell.setBackground(Color.WHITE);
                }
            }
            //marks a cell red if it is a duplicate variable name
            //            if(column == VARIABLE_COL)
            //            {
            //                
            //                boolean dup = false;
            //                String[] columnData = theTable.getColumnData(column);
            //                //check if this is already in the list
            //                for(int i =0; i < columnData.length; i++)
            //                {
            //                    String currTableValue = columnData[i];
            //                    if(currTableValue.equals(cellValue) && i != row)
            //                    {
            //                        dup = true;
            //                        break;
            //                    }
            //                }
            //                //we found a dup
            //                if(dup == true)
            //                {
            //                    cell.setBackground(Color.red);
            //                }
            //            }
            return cell;
        }
    }

    private void savePuzzlejButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_savePuzzlejButtonActionPerformed
        fileChooser.resetChoosableFileFilters();
        fileChooser.setAcceptAllFileFilterUsed(false);

        fileChooser.setDialogTitle("Save Puzzle");

        fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("PDF", "pdf"));
        //        fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("JPEG", "jpeg"));
        //        fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("JPG", "jpg"));
        //        fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("PNG", "png"));
        //        fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("BMP", "bmp"));

        int r = fileChooser.showSaveDialog(this);

        if (r == JFileChooser.APPROVE_OPTION) {

            String name = fileChooser.getSelectedFile().getAbsolutePath();
            String type = fileChooser.getFileFilter().getDescription();

            JPanel jPanelToPrint = printablejPanel;

            if (type.equals("PDF")) { //Save as pdf
                puzzlejTable.setBackground(Color.black);
                try {
                    //                  Document document = new Document(PageSize.A4.rotate(), 50, 50, 50, 50);
                    Document document = new Document(new Rectangle(docWidth, docHeight));
                    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(name + ".pdf"));
                    document.open();
                    PdfContentByte cb = writer.getDirectContent();
                    PdfTemplate tp = cb.createTemplate(jPanelToPrint.getWidth(), jPanelToPrint.getHeight());
                    Graphics2D g2 = tp.createGraphics(jPanelToPrint.getWidth(), jPanelToPrint.getHeight());
                    //g2.scale(0.8, 1.0);
                    jPanelToPrint.print(g2);
                    g2.dispose();
                    cb.addTemplate(tp, 0, 0);
                    document.close();
                } catch (DocumentException ex) {
                    Logger.getLogger(CreatePuzzleJFrame.class.getName()).log(Level.SEVERE, null, ex);
                } catch (FileNotFoundException ex) {
                    Logger.getLogger(CreatePuzzleJFrame.class.getName()).log(Level.SEVERE, null, ex);
                }
                puzzlejTable.setBackground(Color.white);

            } else { //Save as image

                BufferedImage bi = ScreenImage.createImage(jPanelToPrint);
                try {
                    ScreenImage.writeImage(bi, name + "." + type.toLowerCase());
                } catch (IOException ex) {
                    Logger.getLogger(CreatePuzzleJFrame.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }

    }//GEN-LAST:event_savePuzzlejButtonActionPerformed

    private void boxSizejSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_boxSizejSpinnerStateChanged
        //boxSize is new rows' width and columns' height 
        boxSize = (int) boxSizejSpinner.getValue();

        //set new height for all rows
        puzzlejTable.setRowHeight(boxSize);

        //set new width for all columns
        TableColumnModel columnModel = puzzlejTable.getColumnModel();
        int columnCount = columnModel.getColumnCount();

        int oldWidth = boxSize;
        if (boxSize < 15)//because column's min width is 15
            oldWidth = 15;
        int newWidth = (oldWidth * columnCount) + 4;
        int newHeight = boxSize * puzzlejTable.getRowCount() + 4;//+4 to avoid scroll bar
        Dimension d = new Dimension(newWidth, newHeight);
        puzzlejScrollPane.setSize(d);
        //        puzzlejScrollPane.validate();
        //        System.out.println("In BoxSizespinnerstate changed," + puzzlejScrollPane.getSize());
        //        if(boxSize<16)
        //        for(int col=0; col< columnCount; col++){
        //            columnModel.getColumn(col).setWidth(boxSize);
        //        } 
    }//GEN-LAST:event_boxSizejSpinnerStateChanged

    private void gridSizejSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_gridSizejSpinnerStateChanged
        //tweak to avoid blackk recolor of table
        puzzlejTable.getCellRenderer(gridSize - 1, gridSize - 1)
                .getTableCellRendererComponent(puzzlejTable, null, false, true, gridSize - 1, gridSize - 1)
                .setBackground(Color.white);
        //gridSize is no of rows and columns 
        gridSize = (int) gridSizejSpinner.getValue();

        puzzlejTable.setModel(new javax.swing.table.DefaultTableModel(gridSize, gridSize));
        puzzlejTable.setBackground(Color.WHITE);
        acrossCluesjTextArea.setText("");
        downCluesjTextArea.setText("");
        boxSizejSpinnerStateChanged(evt);

        //set new width for all columns
        //        TableColumnModel columnModel = puzzlejTable.getColumnModel();
        //        columnModel.getcaddColumn(new TableColumn(WIDTH));
    }//GEN-LAST:event_gridSizejSpinnerStateChanged

    private void showAnswersjCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showAnswersjCheckBoxActionPerformed
        // TODO add your handling code here:
        if (showAnswersjCheckBox.isSelected()) {
            if (acrossAnsClueHM == null && downAnsClueHM == null) {
                showAnswersjCheckBox.setSelected(false);
                JOptionPane.showMessageDialog(null, "Nothing to display. Kindly generate the puzzle first.",
                        "Nothing to display", JOptionPane.INFORMATION_MESSAGE);
            } else {

                //set table model
                String[] nulls = new String[puzzleGrid.length];
                DefaultTableModel model = new javax.swing.table.DefaultTableModel(puzzleGrid, nulls);
                puzzlejTable.setModel(model);

                //              for(int i=0;i<gridSize;i++)
                //              {
                //                  for(int j=0;j<gridSize;j++)
                //                  {
                //                      DefaultTableModel dtm = (DefaultTableModel) puzzlejTable.getModel();
                //                      if(dtm.getValueAt(i, j).toString().matches(".")==true)
                //                      {
                //                         
                //                      }
                //                  }
                //              }
                puzzlejTable.setDefaultRenderer(Object.class, new CustomCellRenderer());

                acrossCluesjTextArea.setText("");
                downCluesjTextArea.setText("");

                for (String key : acrossAnsClueHM.keySet()) {
                    String value = acrossAnsClueHM.get(key);
                    StringTokenizer strtok = new StringTokenizer(value, "**");
                    int position = Integer.parseInt(strtok.nextToken());
                    int wordNo = Integer.parseInt(strtok.nextToken());
                    String clue = strtok.nextToken();

                    acrossCluesjTextArea.append("" + wordNo + ". " + clue + "\n");

                }
                for (String key : downAnsClueHM.keySet()) {
                    String value = downAnsClueHM.get(key);
                    StringTokenizer strtok = new StringTokenizer(value, "**");
                    int position = Integer.parseInt(strtok.nextToken());
                    int wordNo = Integer.parseInt(strtok.nextToken());
                    String clue = strtok.nextToken();

                    downCluesjTextArea.append("" + wordNo + ". " + clue + "\n");
                }
            }
        } else {
            Character[][] grid = new Character[gridSize][gridSize];
            for (int i = 0; i < gridSize; i++) {
                for (int j = 0; j < gridSize; j++) {
                    if (puzzleGrid[i][j] != '.') {
                        grid[i][j] = ' ';
                    } else {
                        grid[i][j] = '.';
                    }

                }
            }

            //set table model
            String[] nulls = new String[puzzleGrid.length];
            DefaultTableModel model = new javax.swing.table.DefaultTableModel(grid, nulls);
            puzzlejTable.setModel(model);
            //
            //              for(int i=0;i<gridSize;i++)
            //              {
            //                  for(int j=0;j<gridSize;j++)
            //                  {
            //                      DefaultTableModel dtm = (DefaultTableModel) puzzlejTable.getModel();
            //                      if(dtm.getValueAt(i, j).toString().matches(".")==true)
            //                      {
            //                         
            //                      }
            //                  }
            //              }
            puzzlejTable.setDefaultRenderer(Object.class, new CustomCellRenderer());

            acrossCluesjTextArea.setText("");
            downCluesjTextArea.setText("");

            for (String key : acrossAnsClueHM.keySet()) {
                String value = acrossAnsClueHM.get(key);
                StringTokenizer strtok = new StringTokenizer(value, "**");
                int position = Integer.parseInt(strtok.nextToken());
                int wordNo = Integer.parseInt(strtok.nextToken());
                String clue = strtok.nextToken();

                acrossCluesjTextArea.append("" + wordNo + ". " + clue + "\n");

                for (int i = 0; i < gridSize; i++) {
                    for (int j = 0; j < gridSize; j++) {
                        if (puzzleGrid[i][j] != '.') {
                            if ((i * gridSize) + j == position) {
                                puzzlejTable.setValueAt(wordNo, i, j);
                            }
                        }
                    }
                } // bring cell number and then display starting point of word in grid

            }
            for (String key : downAnsClueHM.keySet()) {
                String value = downAnsClueHM.get(key);
                StringTokenizer strtok = new StringTokenizer(value, "**");
                int position = Integer.parseInt(strtok.nextToken());
                int wordNo = Integer.parseInt(strtok.nextToken());
                String clue = strtok.nextToken();

                downCluesjTextArea.append("" + wordNo + ". " + clue + "\n");

                for (int i = 0; i < gridSize; i++) {
                    for (int j = 0; j < gridSize; j++) {
                        if (puzzleGrid[i][j] != '.') {
                            if ((i * gridSize) + j == position) {
                                puzzlejTable.setValueAt(wordNo, i, j);
                            }
                        }
                    }
                }
            }
        }
    }//GEN-LAST:event_showAnswersjCheckBoxActionPerformed

    private void mainjSplitPaneMouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_mainjSplitPaneMouseDragged
        // TODO add your handling code here:
        boxSizejSpinnerStateChanged(null);

    }//GEN-LAST:event_mainjSplitPaneMouseDragged

    private void puzzlejPanelMouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_puzzlejPanelMouseDragged
        // TODO add your handling code here:
    }//GEN-LAST:event_puzzlejPanelMouseDragged

    private void mainjSplitPaneMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_mainjSplitPaneMouseClicked
        // TODO add your handling code here:
    }//GEN-LAST:event_mainjSplitPaneMouseClicked

    private void documentHeightjSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_documentHeightjSpinnerStateChanged
        documentWidthjSpinnerStateChanged(evt);
    }//GEN-LAST:event_documentHeightjSpinnerStateChanged

    private void documentWidthjSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_documentWidthjSpinnerStateChanged
        updateDocSizeFromSpinners();
        //resize jPanel
        Dimension d = new Dimension((int) docWidth, (int) docHeight);
        printablejPanel.setPreferredSize(d);
        //        mainjScrollPane.setPreferredSize(d);
        printablejPanel.revalidate();
        //        mainjScrollPane.revalidate();
        //        System.out.println(mainjScrollPane.getPreferredSize());
        //        d =getSize();
        //        pack();
        //        setSize(d);        
    }//GEN-LAST:event_documentWidthjSpinnerStateChanged

    private void printablejPanelMouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_printablejPanelMouseDragged
        // TODO add your handling code here:
        //        System.out.println("printablejPanelMouseDragged");
    }//GEN-LAST:event_printablejPanelMouseDragged

    private void settingsjButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_settingsjButton1ActionPerformed
        // TODO add your handling code here:
        new AboutJFrame().setVisible(true);
    }//GEN-LAST:event_settingsjButton1ActionPerformed

    /**
     * @param args the command line arguments
     */

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTextArea acrossCluesjTextArea;
    private javax.swing.JLabel boxSizejLabel;
    private javax.swing.JLabel boxSizejLabel1;
    private javax.swing.JSpinner boxSizejSpinner;
    private javax.swing.JPanel cluesjPanel;
    private javax.swing.JSplitPane cluesjSplitPane;
    private javax.swing.JPanel controlsjPanel;
    private javax.swing.JSpinner densityjSpinner;
    private javax.swing.JSpinner documentHeightjSpinner;
    private javax.swing.JSpinner documentWidthjSpinner;
    private javax.swing.JTextArea downCluesjTextArea;
    private javax.swing.JFileChooser fileChooser;
    private javax.swing.JFileChooser fileChooser1;
    private javax.swing.JLabel fileNameLabel;
    private javax.swing.JPanel footjPanel;
    private javax.swing.JButton generatePuzzlejButton;
    private javax.swing.JLabel gridSizejLabel;
    private javax.swing.JLabel gridSizejLabel1;
    private javax.swing.JLabel gridSizejLabel2;
    private javax.swing.JLabel gridSizejLabel3;
    private javax.swing.JSpinner gridSizejSpinner;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane mainjScrollPane;
    private javax.swing.JSplitPane mainjSplitPane;
    private javax.swing.JPanel middlejPanel;
    private javax.swing.JPanel printablejPanel;
    private javax.swing.JPanel puzzlejPanel;
    private javax.swing.JScrollPane puzzlejScrollPane;
    private javax.swing.JTable puzzlejTable;
    private javax.swing.JButton savePuzzlejButton;
    private javax.swing.JButton settingsjButton;
    private javax.swing.JButton settingsjButton1;
    private javax.swing.JCheckBox showAnswersjCheckBox;
    private javax.swing.JLabel titlejLabel;
    // End of variables declaration//GEN-END:variables

    private void updatePuzzleTable() {
    }
}