package UltimaDemo;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileNameExtensionFilter;

import net.miginfocom.swing.MigLayout;
import SDK.SDKlib;
import SDK.SDKlib.Canvas;
import SDK.SDKlib.FontStyle;
import SDK.SDKlib.ImageDef;
import SDK.SDKlib.LineDef;
import SDK.SDKlib.MagTextDef;
import SDK.SDKlib.Return;
import SDK.SDKlib.ShapeDef;
import SDK.SDKlib.ShapeType;
import SDK.SDKlib.TextDef;

import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.ptr.IntByReference;

import static UltimaDemo.Utils.*;
import static UltimaDemo.Main.tabbedPane;

//====================================================================================

class PrintDemo implements Printable {
	class ColorCombo {
	    private String key;
	    private Color value;

	    public ColorCombo(String key, Color value) {
	        this.key   = key;
	        this.value = value;
	    }

	    @Override
	    public String toString() {return key;}
	    public Color  getValue() {return value;}
	}

	private final int MAX_TEXT_SIZE      = 50;
	private final int MAX_SHAPE_WIDTH    = 50;
	private final int MAX_LINE_WIDTH     = 50;
	
	private final int FRONT_TEXT_X       = 10;
	private final int FRONT_TEXT_Y       = 50;
	private final int FRONT_TEXT_SIZE    = 10;
	private final int FRONT_SHAPE_L      = 60;
	private final int FRONT_SHAPE_T      = 160;
	private final int FRONT_SHAPE_B      = 320;
	private final int FRONT_SHAPE_R      = 320;
	private final int FRONT_SHAPE_WIDTH  = 5;
	private final int FRONT_LINE_START_X = 10;
	private final int FRONT_LINE_START_Y = 10;
	private final int FRONT_LINE_END_X   = 800;
	private final int FRONT_LINE_END_Y   = 150;
	private final int FRONT_LINE_WIDTH   = 8;
	private final int FRONT_IMAGE_X      = 50;
	private final int FRONT_IMAGE_Y      = 110;
	private final int FRONT_IMAGE_P1     = 0;
	private final int FRONT_IMAGE_P2     = 0;

	private final int BACK_TEXT_X        = 10;
	private final int BACK_TEXT_Y        = 50;
	private final int BACK_TEXT_SIZE     = 10;
	private final int BACK_SHAPE_L       = 60;
	private final int BACK_SHAPE_T       = 160;
	private final int BACK_SHAPE_B       = 320;
	private final int BACK_SHAPE_R       = 320;
	private final int BACK_SHAPE_WIDTH   = 5;
	private final int BACK_LINE_START_X  = 10;
	private final int BACK_LINE_START_Y  = 10;
	private final int BACK_LINE_END_X    = 800;
	private final int BACK_LINE_END_Y    = 150;
	private final int BACK_LINE_WIDTH    = 8;
	private final int BACK_IMAGE_X       = 50;
	private final int BACK_IMAGE_Y       = 110;
	private final int BACK_IMAGE_P1      = 0;
	private final int BACK_IMAGE_P2      = 0;

	private final String FRONT      = "Front";
	private final String BACK       = "Back";
	private final String FRONTIMAGE = "FrontImage";
	private final String BACKIMAGE  = "BackImage";
	private final String PRINT      = "Print";
	private final String PRINTPREFS = "PrintPrefs";

	private final ActionHandler ah = new ActionHandler();

	public static final JPanel panelPrintDemo = new JPanel();
	public static final String PRINTDEMO_TAB_TITLE = "Print Demo";

	private final JPanel panelCardSides = new JPanel();
	private final JCheckBox checkCardFront = new JCheckBox("Card Front");
	private final JCheckBox checkCardBack = new JCheckBox("Card Back");
	private final JTabbedPane tabbedCardSidePane = new JTabbedPane(JTabbedPane.TOP);
	private final JPanel tabFront = new JPanel();
	private final JPanel tabBack = new JPanel();
    
	private final JPanel panelFrontText = new JPanel();
	private final JLabel labelFrontText = new JLabel("Text");
    private final JCheckBox checkFrontText = new JCheckBox("Enabled");
	private final JLabel labelFrontTextColour = new JLabel("Colour");
	private final JLabel labelFrontTextPosition = new JLabel("Position:");
	private final JComboBox<ColorCombo> comboFrontTextColour = new JComboBox<ColorCombo>();
	private final JCheckBox checkFrontBold = new JCheckBox("Bold");
	private final JCheckBox checkFrontItalic = new JCheckBox("Italic");
	private final JCheckBox checkFrontUnderline = new JCheckBox("Underline");
	private final JCheckBox checkFrontStrike = new JCheckBox("Strikethrough");
	private final JTextField textFrontText = new JTextField();
	private final JLabel labelFrontTextX = new JLabel("X");
	private final JSpinner spinnerFrontTextX = new JSpinner(new SpinnerNumberModel(FRONT_TEXT_X, 0, MAX_X_COORD, 1));
	private final JLabel labelFrontTextY = new JLabel("Y");
	private final JSpinner spinnerFrontTextY = new JSpinner(new SpinnerNumberModel(FRONT_TEXT_Y, 0, MAX_Y_COORD, 1));
	private final JLabel labelFrontTextSize = new JLabel("Size");
	private final JSpinner spinnerFrontTextSize = new JSpinner(new SpinnerNumberModel(FRONT_TEXT_SIZE, 0, MAX_TEXT_SIZE, 1));
	private final JCheckBox checkFrontTextResin = new JCheckBox("USe Resin");
    
	private final JPanel panelFrontShape = new JPanel();
	private final JLabel labelFrontShape = new JLabel("Shape");
    private final JCheckBox checkFrontShape = new JCheckBox("Enabled");
	private final JComboBox<ComboItem> comboFrontShape = new JComboBox<ComboItem>();
	private final JLabel labelFrontShapeOutline = new JLabel("Outline");
	private final JComboBox<ColorCombo> comboFrontShapeOutline = new JComboBox<ColorCombo>();
	private final JLabel labelFrontShapeFill = new JLabel("Fill");
	private final JComboBox<ColorCombo> comboFrontShapeFill = new JComboBox<ColorCombo>();
	private final JLabel labelFrontShapeL = new JLabel("L");
	private final JSpinner spinnerFrontShapeL = new JSpinner(new SpinnerNumberModel(FRONT_SHAPE_L, 0, MAX_X_COORD, 1));
	private final JLabel labelFrontShapeT = new JLabel("T");
	private final JSpinner spinnerFrontShapeT = new JSpinner(new SpinnerNumberModel(FRONT_SHAPE_T, 0, MAX_Y_COORD, 1));
	private final JLabel labelFrontShapeB = new JLabel("B");
	private final JSpinner spinnerFrontShapeB = new JSpinner(new SpinnerNumberModel(FRONT_SHAPE_B, 0, MAX_Y_COORD, 1));
	private final JLabel labelFrontShapeR = new JLabel("R");
	private final JSpinner spinnerFrontShapeR = new JSpinner(new SpinnerNumberModel(FRONT_SHAPE_R, 0, MAX_X_COORD, 1));
	private final JLabel labelFrontShapeWidth = new JLabel("Width");
	private final JSpinner spinnerFrontShapeWidth = new JSpinner(new SpinnerNumberModel(FRONT_SHAPE_WIDTH, 0, MAX_SHAPE_WIDTH, 1));
	private final JCheckBox checkFrontShapeResin = new JCheckBox("Use Resin");

	private final JPanel panelFrontLine = new JPanel();
	private final JLabel labelFrontLine = new JLabel("Line:");
    private final JCheckBox checkFrontLine = new JCheckBox("Enabled");
	private final JLabel labelFrontLineColour = new JLabel("Colour");
	private final JComboBox<ColorCombo> comboFrontLineColour = new JComboBox<ColorCombo>();
	private final JLabel labelFrontLineStart = new JLabel("Start:");
	private final JLabel labelFrontLineStartX = new JLabel("X");
	private final JSpinner spinnerFrontLineStartX = new JSpinner(new SpinnerNumberModel(FRONT_LINE_START_X, 0, MAX_X_COORD, 1));
	private final JLabel labelFrontLineStartY = new JLabel("Y");
	private final JSpinner spinnerFrontLineStartY = new JSpinner(new SpinnerNumberModel(FRONT_LINE_START_Y, 0, MAX_Y_COORD, 1));
	private final JLabel labelFrontLineEnd = new JLabel("End:");
	private final JLabel labelFrontLineEndX = new JLabel("X");
	private final JSpinner spinnerFrontLineEndX = new JSpinner(new SpinnerNumberModel(FRONT_LINE_END_X, 0, MAX_X_COORD, 1));
	private final JLabel labelFrontLineEndY = new JLabel("Y");
	private final JSpinner spinnerFrontLineEndY = new JSpinner(new SpinnerNumberModel(FRONT_LINE_END_Y, 0, MAX_Y_COORD, 1));
	private final JLabel labelFrontLineWidth = new JLabel("Width");
	private final JSpinner spinnerFrontLineWidth = new JSpinner(new SpinnerNumberModel(FRONT_LINE_WIDTH, 0, MAX_LINE_WIDTH, 1));
	private final JCheckBox checkFrontLineResin = new JCheckBox("Use Resin");

	private final JPanel panelFrontImage = new JPanel();
	private final JLabel labelFrontImage = new JLabel("Image");
    private final JCheckBox checkFrontImage = new JCheckBox("Enabled");
	private final JTextField textFrontImage = new JTextField();
	private final JButton btnFrontImage = new JButton("...");
	private final JLabel labelFrontImagePosition = new JLabel("Position:");
	private final JLabel labelFrontImageX = new JLabel("X");
	private final JSpinner spinnerFrontImageX = new JSpinner(new SpinnerNumberModel(FRONT_IMAGE_X, 0, MAX_X_COORD, 1));
	private final JLabel labelFrontImageY = new JLabel("Y");
	private final JSpinner spinnerFrontImageY = new JSpinner(new SpinnerNumberModel(FRONT_IMAGE_Y, 0, MAX_Y_COORD, 1));
	private final JLabel labelFrontImageP1 = new JLabel("P1");
	private final JSpinner spinnerFrontImageP1 = new JSpinner(new SpinnerNumberModel(FRONT_IMAGE_P1, 0, MAX_CARD_LENGTH, 1));
	private final JLabel labelFrontImageP2 = new JLabel("P2");
	private final JSpinner spinnerFrontImageP2 = new JSpinner(new SpinnerNumberModel(FRONT_IMAGE_P2, 0, MAX_CARD_HEIGHT, 1));
    private final JCheckBox checkFrontImageResin = new JCheckBox("Use Resin");

	private final JPanel panelBackText = new JPanel();
	private final JLabel labelBackText = new JLabel("Text");
    private final JCheckBox checkBackText = new JCheckBox("Enabled");
	private final JTextField textBackText = new JTextField();
	private final JLabel labelBackTextColour = new JLabel("Colour");
	private final JComboBox<ColorCombo> comboBackTextColour = new JComboBox<ColorCombo>();
	private final JCheckBox checkBackBold = new JCheckBox("Bold");
	private final JCheckBox checkBackItalic = new JCheckBox("Italic");
	private final JCheckBox checkBackUnderline = new JCheckBox("Underline");
	private final JCheckBox checkBackStrike = new JCheckBox("Strikethrough");
	private final JLabel labelBackTextPosition = new JLabel("Position:");
	private final JLabel labelBackTextX = new JLabel("X");
	private final JSpinner spinnerBackTextX = new JSpinner(new SpinnerNumberModel(BACK_TEXT_X, 0, MAX_X_COORD, 1));
	private final JLabel labelBackTextY = new JLabel("Y");
	private final JSpinner spinnerBackTextY = new JSpinner(new SpinnerNumberModel(BACK_TEXT_Y, 0, MAX_Y_COORD, 1));
	private final JLabel labelBackTextSize = new JLabel("Size");
	private final JSpinner spinnerBackTextSize = new JSpinner(new SpinnerNumberModel(BACK_TEXT_SIZE, 0, MAX_TEXT_SIZE, 1));
	private final JCheckBox checkBackTextResin = new JCheckBox("Use Resin");

	private final JPanel panelBackShape = new JPanel();
	private final JLabel labelBackShape = new JLabel("Shape");
    private final JCheckBox checkBackShape = new JCheckBox("Enabled");
	private final JComboBox<ComboItem> comboBackShape = new JComboBox<ComboItem>();
	private final JLabel labelBackShapeOutline = new JLabel("Outline");
	private final JComboBox<ColorCombo> comboBackShapeOutline = new JComboBox<ColorCombo>();
	private final JLabel labelBackShapeFill = new JLabel("Fill");
	private final JComboBox<ColorCombo> comboBackShapeFill = new JComboBox<ColorCombo>();
	private final JLabel labelBackShapeL = new JLabel("L");
	private final JSpinner spinnerBackShapeL = new JSpinner(new SpinnerNumberModel(BACK_SHAPE_L, 0, MAX_X_COORD, 1));
	private final JLabel labelBackShapeT = new JLabel("T");
	private final JSpinner spinnerBackShapeT = new JSpinner(new SpinnerNumberModel(BACK_SHAPE_T, 0, MAX_Y_COORD, 1));
	private final JLabel labelBackShapeB = new JLabel("B");
	private final JSpinner spinnerBackShapeB = new JSpinner(new SpinnerNumberModel(BACK_SHAPE_B, 0, MAX_Y_COORD, 1));
	private final JLabel labelBackShapeR = new JLabel("R");
	private final JSpinner spinnerBackShapeR = new JSpinner(new SpinnerNumberModel(BACK_SHAPE_R, 0, MAX_X_COORD, 1));
	private final JLabel labelBackShapeWidth = new JLabel("Width");
	private final JSpinner spinnerBackShapeWidth = new JSpinner(new SpinnerNumberModel(BACK_SHAPE_WIDTH, 0, MAX_LINE_WIDTH, 1));
	private final JCheckBox checkBackShapeResin = new JCheckBox("Use Resin");

	private final JPanel panelBackLine = new JPanel();
	private final JLabel labelBackLine = new JLabel("Line:");
    private final JCheckBox checkBackLine = new JCheckBox("Enabled");
	private final JLabel labelBackLineColour = new JLabel("Colour");
	private final JComboBox<ColorCombo> comboBackLineColour = new JComboBox<ColorCombo>();
	private final JLabel labelBackLineStart = new JLabel("Start:");
	private final JLabel labelBackLineStartX = new JLabel("X");
	private final JSpinner spinnerBackLineStartX = new JSpinner(new SpinnerNumberModel(BACK_LINE_START_X, 0, MAX_X_COORD, 1));
	private final JLabel labelBackLineStartY = new JLabel("Y");
	private final JSpinner spinnerBackLineStartY = new JSpinner(new SpinnerNumberModel(BACK_LINE_START_Y, 0, MAX_Y_COORD, 1));
	private final JLabel labelBackLineEnd = new JLabel("End:");
	private final JLabel labelBackLineEndX = new JLabel("X");
	private final JSpinner spinnerBackLineEndX = new JSpinner(new SpinnerNumberModel(BACK_LINE_END_X, 0, MAX_X_COORD, 1));
	private final JLabel labelBackLineEndY = new JLabel("Y");
	private final JSpinner spinnerBackLineEndY = new JSpinner(new SpinnerNumberModel(BACK_LINE_END_Y, 0, MAX_Y_COORD, 1));
	private final JLabel labelBackLineWidth = new JLabel("Width");
	private final JSpinner spinnerBackLineWidth = new JSpinner(new SpinnerNumberModel(BACK_LINE_WIDTH, 0, MAX_LINE_WIDTH, 1));
	private final JCheckBox checkBackLineResin = new JCheckBox("Use Resin");
    
	private final JPanel panelBackImage = new JPanel();
	private final JLabel labelBackImage = new JLabel("Image");
    private final JCheckBox checkBackImage = new JCheckBox("Enabled");
	private final JTextField textBackImage = new JTextField();
	private final JButton btnBackImage = new JButton("...");
	private final JLabel labelBackImagePosition = new JLabel("Position:");
	private final JLabel labelBackImageX = new JLabel("X");
	private final JSpinner spinnerBackImageX = new JSpinner(new SpinnerNumberModel(BACK_IMAGE_X, 0, MAX_X_COORD, 1));
	private final JLabel labelBackImageY = new JLabel("Y");
	private final JSpinner spinnerBackImageY = new JSpinner(new SpinnerNumberModel(BACK_IMAGE_Y, 0, MAX_Y_COORD, 1));
	private final JLabel labelBackImageP1 = new JLabel("P1");
	private final JSpinner spinnerBackImageP1 = new JSpinner(new SpinnerNumberModel(BACK_IMAGE_P1, 0, MAX_CARD_LENGTH, 1));
	private final JLabel labelBackImageP2 = new JLabel("P2");
	private final JSpinner spinnerBackImageP2 = new JSpinner(new SpinnerNumberModel(BACK_IMAGE_P2, 0, MAX_CARD_HEIGHT, 1));
    private final JCheckBox checkBackImageResin = new JCheckBox("Use Resin");

    private final JPanel panelMagTracks = new JPanel();
    private final JCheckBox checkMagData = new JCheckBox("Enabled");
    private final JLabel labelTrack1 = new JLabel("Track 1");
    private final JLabel labelTrack2 = new JLabel("Track 2");
    private final JLabel labelTrack3 = new JLabel("Track 3");
    private final JTextField textMag1Data = new JTextField();
    private final JTextField textMag2Data = new JTextField();
    private final JTextField textMag3Data = new JTextField();

    private final JButton btnPrinterPrefs = new JButton("Printer Preferences");
    private final JCheckBox checkNativePrint = new JCheckBox("Use Native Printing");
	private final JButton btnPrint = new JButton("Print");
    
    private final Color TRANSPARENT = new Color(0, 0, 0, 0);

	private HANDLE hSession;
    private SDKlib SDK;

    //====================================================================================

    public PrintDemo() {
        panelPrintDemo.setLayout(new MigLayout("", "[grow][grow,center][][grow]", "[:25.00:30.00,center][2.00][grow][]"));
        
        panelPrintDemo.add(panelCardSides, "cell 0 0 4 1,grow");
        panelCardSides.setLayout(new MigLayout("", "[grow][grow]", "[]"));
        checkCardFront.setSelected(true);
        
        panelCardSides.add(checkCardFront, "cell 0 0,alignx center,aligny center");
        checkCardFront.setActionCommand(FRONT);
        checkCardFront.addActionListener(ah);
        panelCardSides.add(checkCardBack, "cell 1 0,alignx center,aligny center");
        checkCardBack.setActionCommand(BACK);
        checkCardBack.addActionListener(ah);
        
        panelPrintDemo.add(tabbedCardSidePane, "cell 0 2 4 1,grow");

        //##### FRONT TAB #####
        tabbedCardSidePane.addTab("Front", null, tabFront, null);
        tabbedCardSidePane.setEnabledAt(0, true);
        tabFront.setLayout(new MigLayout("", "[]", "[][][][]"));
        tabFront.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "", TitledBorder.LEADING, TitledBorder.TOP, null, new Color(0, 0, 0)));
        
        //===== Front Text =====
        tabFront.add(panelFrontText, "cell 0 0,grow");
        panelFrontText.setLayout(new MigLayout("", "[grow][18%,grow][18%,grow][18%,grow][18%,grow][18%,grow]", "[][][][]"));
        panelFrontText.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
        						                  "",
        						                  TitledBorder.LEADING, 
        						                  TitledBorder.TOP, 
        						                  null,
        						                  new Color(0, 0, 0)));
        panelFrontText.add(checkFrontText, "cell 0 0 5 1");
        checkFrontText.setActionCommand(FRONT);
        checkFrontText.addActionListener(ah);
        checkFrontText.setSelected(true);
        
        panelFrontText.add(labelFrontText, "cell 0 1,alignx left");
        panelFrontText.add(textFrontText, "cell 1 1 5 1,growx");
        textFrontText.setText("FRONT - First Line of Java Text");

        panelFrontText.add(checkFrontTextResin, "cell 5 0,alignx right");
        checkFrontTextResin.setHorizontalTextPosition(SwingConstants.LEFT);
        
        panelFrontText.add(labelFrontTextColour, "cell 0 2,alignx left");
        panelFrontText.add(comboFrontTextColour, "cell 1 2,growx");
        comboFrontTextColour.addItem(new ColorCombo("Red",     Color.red));
        comboFrontTextColour.addItem(new ColorCombo("Green",   Color.green));   
        comboFrontTextColour.addItem(new ColorCombo("Blue",    Color.blue));   
        comboFrontTextColour.addItem(new ColorCombo("Cyan",    Color.cyan));    
        comboFrontTextColour.addItem(new ColorCombo("Magenta", Color.magenta)); 
        comboFrontTextColour.addItem(new ColorCombo("Yellow",  Color.yellow));  
        comboFrontTextColour.addItem(new ColorCombo("White",   Color.white));   
        comboFrontTextColour.addItem(new ColorCombo("Black",   Color.black)); 
        
        panelFrontText.add(checkFrontBold, "cell 2 2");
        panelFrontText.add(checkFrontItalic, "cell 3 2");
        panelFrontText.add(checkFrontUnderline, "cell 4 2");
        panelFrontText.add(checkFrontStrike, "cell 5 2");
        
        panelFrontText.add(labelFrontTextPosition, "cell 0 3");
        panelFrontText.add(labelFrontTextX, "flowx,cell 1 3");
        panelFrontText.add(spinnerFrontTextX, "cell 1 3,alignx right");
        spinnerFrontTextX.setEditor(new JSpinner.NumberEditor(spinnerFrontTextX,"#"));
        
        panelFrontText.add(labelFrontTextY, "flowx,cell 2 3");
        panelFrontText.add(spinnerFrontTextY, "cell 2 3");
        spinnerFrontTextY.setEditor(new JSpinner.NumberEditor(spinnerFrontTextY,"#"));
        
        panelFrontText.add(labelFrontTextSize, "cell 3 3,alignx right");
        panelFrontText.add(spinnerFrontTextSize, "cell 4 3,growx");
        
        //===== Front Shape =====
        tabFront.add(panelFrontShape, "cell 0 1,grow");
        panelFrontShape.setLayout(new MigLayout("", "[][62.00,grow,leading][grow][grow][grow][grow]", "[][][]"));
        panelFrontShape.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
        		                                   "",
        										   TitledBorder.LEADING, 
        										   TitledBorder.TOP, 
        										   null,
				                                   new Color(0, 0, 0)));
        
        panelFrontShape.add(checkFrontShape, "cell 0 0 5 1");
        checkFrontShape.setActionCommand(FRONT);
        checkFrontShape.addActionListener(ah);
        checkFrontShape.setSelected(true);
        
        panelFrontShape.add(checkFrontShapeResin, "cell 5 0,alignx right");
        checkFrontShapeResin.setHorizontalTextPosition(SwingConstants.LEFT);
        
        panelFrontShape.add(labelFrontShape, "cell 0 1,alignx left");
        panelFrontShape.add(comboFrontShape, "cell 1 1,growx");
        comboFrontShape.addItem(new ComboItem("Rectangle", ShapeType.RECTANGLE));
        comboFrontShape.addItem(new ComboItem("Ellipse",   ShapeType.ELLIPSE));
        comboFrontShape.addItem(new ComboItem("RoundRect", ShapeType.ROUND_RECT));
        comboFrontShape.addItem(new ComboItem("Pie",       ShapeType.PIE));
        comboFrontShape.addItem(new ComboItem("Chord",     ShapeType.CHORD));
        
        panelFrontShape.add(labelFrontShapeL, "flowx,cell 2 1,alignx right");
        panelFrontShape.add(spinnerFrontShapeL, "cell 2 1,growx");
        spinnerFrontShapeL.setEditor(new JSpinner.NumberEditor(spinnerFrontShapeL,"#"));
        
        panelFrontShape.add(labelFrontShapeT, "flowx,cell 3 1,alignx right");
        panelFrontShape.add(spinnerFrontShapeT, "cell 3 1,growx");
        spinnerFrontShapeT.setEditor(new JSpinner.NumberEditor(spinnerFrontShapeT,"#"));
        
        panelFrontShape.add(labelFrontShapeR, "flowx,cell 4 1,alignx right");
        panelFrontShape.add(spinnerFrontShapeR, "cell 4 1,growx");
        spinnerFrontShapeR.setEditor(new JSpinner.NumberEditor(spinnerFrontShapeR,"#"));
        
        panelFrontShape.add(labelFrontShapeB, "flowx,cell 5 1,alignx right");
        panelFrontShape.add(spinnerFrontShapeB, "cell 5 1,growx");
        spinnerFrontShapeB.setEditor(new JSpinner.NumberEditor(spinnerFrontShapeB,"#"));
        
        panelFrontShape.add(labelFrontShapeOutline, "cell 0 2,alignx left");
        panelFrontShape.add(comboFrontShapeOutline, "cell 1 2,growx");
        comboFrontShapeOutline.addItem(new ColorCombo("Red",     Color.red));     
        comboFrontShapeOutline.addItem(new ColorCombo("Green",   Color.green));    
        comboFrontShapeOutline.addItem(new ColorCombo("Blue",    Color.blue));     
        comboFrontShapeOutline.addItem(new ColorCombo("Cyan",    Color.cyan));      
        comboFrontShapeOutline.addItem(new ColorCombo("Magenta", Color.magenta)); 
        comboFrontShapeOutline.addItem(new ColorCombo("Yellow",  Color.yellow));  
        comboFrontShapeOutline.addItem(new ColorCombo("White",   Color.white));    
        comboFrontShapeOutline.addItem(new ColorCombo("Black",   Color.black));   
        
        panelFrontShape.add(labelFrontShapeFill, "flowx,cell 2 2,alignx right");
        panelFrontShape.add(comboFrontShapeFill, "cell 3 2,growx");
        comboFrontShapeFill.addItem(new ColorCombo("Red",     Color.red));     
        comboFrontShapeFill.addItem(new ColorCombo("Green",   Color.green));    
        comboFrontShapeFill.addItem(new ColorCombo("Blue",    Color.blue));     
        comboFrontShapeFill.addItem(new ColorCombo("Cyan",    Color.cyan));      
        comboFrontShapeFill.addItem(new ColorCombo("Magenta", Color.magenta)); 
        comboFrontShapeFill.addItem(new ColorCombo("Yellow",  Color.yellow));  
        comboFrontShapeFill.addItem(new ColorCombo("White",   Color.white));    
        comboFrontShapeFill.addItem(new ColorCombo("Black",   Color.black));   
        comboFrontShapeFill.addItem(new ColorCombo("Transparent", TRANSPARENT));
        comboFrontShapeFill.setSelectedIndex(comboFrontShapeFill.getItemCount() - 1);
        
        panelFrontShape.add(labelFrontShapeWidth, "flowx,cell 4 2,alignx right");
        panelFrontShape.add(spinnerFrontShapeWidth, "cell 4 2,alignx right");
        
        //===== Front Line =====
        tabFront.add(panelFrontLine, "cell 0 2,grow");
        panelFrontLine.setLayout(new MigLayout("", "[][33.00:n][][][33.00:n][55.00][][grow][grow]", "[][][]"));
        panelFrontLine.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
        		                                  "",
		                                  TitledBorder.LEADING, 
		                                  TitledBorder.TOP, 
		                                  null,
		                                  new Color(0, 0, 0)));
        panelFrontLine.add(checkFrontLine, "cell 0 0 8 1");
        checkFrontLine.setActionCommand(FRONT);
        checkFrontLine.addActionListener(ah);
        checkFrontLine.setSelected(true);

        panelFrontLine.add(checkFrontLineResin, "cell 8 0,alignx right");
        checkFrontLineResin.setHorizontalTextPosition(SwingConstants.LEFT);

        panelFrontLine.add(labelFrontLine, "cell 0 1");
        panelFrontLine.add(labelFrontLineColour, "flowx,cell 1 1 4 1");
        panelFrontLine.add(comboFrontLineColour, "cell 1 1 4 1,growx");
        comboFrontLineColour.addItem(new ColorCombo("Red",     Color.red));     
        comboFrontLineColour.addItem(new ColorCombo("Green",   Color.green));     
        comboFrontLineColour.addItem(new ColorCombo("Blue",    Color.blue));      
        comboFrontLineColour.addItem(new ColorCombo("Cyan",    Color.cyan));       
        comboFrontLineColour.addItem(new ColorCombo("Magenta", Color.magenta)); 
        comboFrontLineColour.addItem(new ColorCombo("Yellow",  Color.yellow));   
        comboFrontLineColour.addItem(new ColorCombo("White",   Color.white));     
        comboFrontLineColour.addItem(new ColorCombo("Black",   Color.black));   
        
        panelFrontLine.add(labelFrontLineWidth, "cell 6 1");
        panelFrontLine.add(spinnerFrontLineWidth, "cell 7 1,growx");
        
        panelFrontLine.add(labelFrontLineStart, "cell 0 2");
        panelFrontLine.add(labelFrontLineStartX, "flowx,cell 1 2 3 1");
        panelFrontLine.add(spinnerFrontLineStartX, "cell 1 2 3 1,growx");
        spinnerFrontLineStartX.setEditor(new JSpinner.NumberEditor(spinnerFrontLineStartX,"#"));

        panelFrontLine.add(labelFrontLineStartY, "flowx,cell 4 2 2 1");
        panelFrontLine.add(spinnerFrontLineStartY, "cell 4 2 2 1,growx");
        spinnerFrontLineStartY.setEditor(new JSpinner.NumberEditor(spinnerFrontLineStartY,"#"));
        
        panelFrontLine.add(labelFrontLineEnd, "cell 6 2");
        panelFrontLine.add(labelFrontLineEndX, "flowx,cell 7 2");
        panelFrontLine.add(spinnerFrontLineEndX, "cell 7 2,growx");
        spinnerFrontLineEndX.setEditor(new JSpinner.NumberEditor(spinnerFrontLineEndX,"#"));

        panelFrontLine.add(labelFrontLineEndY, "flowx,cell 8 2");
        panelFrontLine.add(spinnerFrontLineEndY, "cell 8 2,growx");
        spinnerFrontLineEndY.setEditor(new JSpinner.NumberEditor(spinnerFrontLineEndY,"#"));
        
        //===== Front Image =====
        tabFront.add(panelFrontImage, "cell 0 3,grow");
        panelFrontImage.setLayout(new MigLayout("", "[20%][20%][20%][20%][20%][]", "[][][]"));
        panelFrontImage.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
                                                   "",
                		                           TitledBorder.LEADING, 
                                                   TitledBorder.TOP, 
                                                   null,
        		                                   new Color(0, 0, 0)));
        panelFrontImage.add(checkFrontImage, "flowx,cell 0 0 6 1");
        checkFrontImage.setActionCommand(FRONT);
        checkFrontImage.addActionListener(ah);

        panelFrontImage.add(checkFrontImageResin, "cell 5 0");
        checkFrontImageResin.setHorizontalTextPosition(SwingConstants.LEFT);
        checkFrontImageResin.setEnabled(false);

        panelFrontImage.add(labelFrontImage, "cell 0 1,alignx left");
        panelFrontImage.add(textFrontImage, "cell 1 1 4 1,growx");
        textFrontImage.setEnabled(false);

        panelFrontImage.add(btnFrontImage, "cell 5 1");
        btnFrontImage.setEnabled(false);
        btnFrontImage.setActionCommand(FRONTIMAGE);
        btnFrontImage.addActionListener(ah);

        panelFrontImage.add(labelFrontImagePosition, "cell 0 2");
        panelFrontImage.add(labelFrontImageX, "flowx,cell 1 2");
        panelFrontImage.add(spinnerFrontImageX, "cell 1 2,growx");
        spinnerFrontImageX.setEditor(new JSpinner.NumberEditor(spinnerFrontImageX,"#"));
        spinnerFrontImageX.setEnabled(false);

        panelFrontImage.add(labelFrontImageY, "flowx,cell 2 2");
        panelFrontImage.add(spinnerFrontImageY, "cell 2 2,growx");
        spinnerFrontImageY.setEditor(new JSpinner.NumberEditor(spinnerFrontImageY,"#"));
        spinnerFrontImageY.setEnabled(false);

        panelFrontImage.add(labelFrontImageP1, "flowx,cell 3 2");
        panelFrontImage.add(spinnerFrontImageP1, "cell 3 2,growx");
        spinnerFrontImageP1.setEditor(new JSpinner.NumberEditor(spinnerFrontImageP1,"#"));
        spinnerFrontImageP2.setEnabled(false);
        
        panelFrontImage.add(labelFrontImageP2, "flowx,cell 4 2");
        panelFrontImage.add(spinnerFrontImageP2, "cell 4 2,growx");
        spinnerFrontImageP2.setEditor(new JSpinner.NumberEditor(spinnerFrontImageP2,"#"));
        spinnerFrontImageP1.setEnabled(false);

        //===== Mag Tracks =====
        tabFront.add(panelMagTracks, "cell 0 4,grow");
        panelMagTracks.setLayout(new MigLayout("", "[][grow]", "[][][][]"));
        panelMagTracks.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
                		                          "",
                		                          TitledBorder.LEADING, 
                		                          TitledBorder.TOP, 
                		                          null,
                		                          new Color(0, 0, 0)));
        panelMagTracks.add(checkMagData, "cell 0 0");
        checkMagData.setActionCommand(FRONT);
        checkMagData.addActionListener(ah);
        labelTrack1.setEnabled(false);

        panelMagTracks.add(labelTrack1, "flowx,cell 0 1,alignx left");
        textMag1Data.setEnabled(false);
        panelMagTracks.add(textMag1Data, "cell 1 1,growx");
        labelTrack2.setEnabled(false);
        panelMagTracks.add(labelTrack2, "cell 0 2,alignx left");
        textMag2Data.setEnabled(false);
        panelMagTracks.add(textMag2Data, "cell 1 2,growx");
        labelTrack3.setEnabled(false);
        panelMagTracks.add(labelTrack3, "cell 0 3,alignx left");
        textMag3Data.setEnabled(false);
        panelMagTracks.add(textMag3Data, "cell 1 3,growx");
        
        
        //##### BACK TAB #####
        tabbedCardSidePane.addTab("Back", null, tabBack, null);
        tabbedCardSidePane.setEnabledAt(1, true);
        tabBack.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "", TitledBorder.LEADING, TitledBorder.TOP, null, new Color(0, 0, 0)));
        tabBack.setLayout(new MigLayout("", "[grow]", "[][][][][]"));
        
        //===== Back Text =====
        tabBack.add(panelBackText, "cell 0 0,grow");
        panelBackText.setLayout(new MigLayout("", "[grow][18%,grow][18%,grow][18%,grow][18%,grow][18%,grow]", "[][][][]"));
        panelBackText.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
        		                                 "",
        		                                 TitledBorder.LEADING, 
        		                                 TitledBorder.TOP, 
        		                                 null,
        		                                 new Color(0, 0, 0)));
        panelBackText.add(checkBackText, "flowx,cell 0 0 5 1");
        checkBackText.setActionCommand(BACK);
        checkBackText.addActionListener(ah);
        checkBackText.setEnabled(false);
        
        panelBackText.add(labelBackText, "cell 0 1,alignx left");
        panelBackText.add(textBackText, "cell 1 1 5 1,growx");
        textBackText.setEnabled(false);
        textBackText.setText("BACK - First Line of Java Text");
                
        panelBackText.add(checkBackTextResin, "cell 5 0,alignx right");
        checkBackTextResin.setHorizontalTextPosition(SwingConstants.LEFT);
        checkBackTextResin.setEnabled(false);
        
        panelBackText.add(labelBackTextColour, "cell 0 2,alignx left");
        comboBackTextColour.setEnabled(false);
        panelBackText.add(comboBackTextColour, "cell 1 2,growx");
        comboBackTextColour.addItem(new ColorCombo("Red",     Color.red));     
        comboBackTextColour.addItem(new ColorCombo("Green",   Color.green));      
        comboBackTextColour.addItem(new ColorCombo("Blue",    Color.blue));       
        comboBackTextColour.addItem(new ColorCombo("Cyan",    Color.cyan));        
        comboBackTextColour.addItem(new ColorCombo("Magenta", Color.magenta));  
        comboBackTextColour.addItem(new ColorCombo("Yellow",  Color.yellow));    
        comboBackTextColour.addItem(new ColorCombo("White",   Color.white));      
        comboBackTextColour.addItem(new ColorCombo("Black",   Color.black));
        checkBackBold.setEnabled(false);
                        
        panelBackText.add(checkBackBold, "cell 2 2");
        checkBackItalic.setEnabled(false);
        panelBackText.add(checkBackItalic, "cell 3 2");
        checkBackUnderline.setEnabled(false);
        panelBackText.add(checkBackUnderline, "cell 4 2");
        checkBackStrike.setEnabled(false);
        panelBackText.add(checkBackStrike, "cell 5 2");
        
        panelBackText.add(labelBackTextPosition, "cell 0 3,alignx left");
        panelBackText.add(labelBackTextX, "flowx,cell 1 3");
        panelBackText.add(spinnerBackTextX, "cell 1 3");
        spinnerBackTextX.setEditor(new JSpinner.NumberEditor(spinnerBackTextX,"#"));
        spinnerBackTextX.setEnabled(false);

        panelBackText.add(labelBackTextY, "flowx,cell 2 3");
        panelBackText.add(spinnerBackTextY, "cell 2 3");
        spinnerBackTextY.setEditor(new JSpinner.NumberEditor(spinnerBackTextY,"#"));
        spinnerBackTextY.setEnabled(false);
        
        panelBackText.add(labelBackTextSize, "cell 3 3,alignx right");
        panelBackText.add(spinnerBackTextSize, "cell 4 3,growx");
        spinnerBackTextSize.setEnabled(false);
        
        //===== Back Shape =====
        tabBack.add(panelBackShape, "cell 0 1,grow");
        panelBackShape.setLayout(new MigLayout("", "[][62.00,grow,leading][grow][grow][grow][grow]", "[][][]"));
        panelBackShape.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
        		                                  "",
        		                                  TitledBorder.LEADING, 
        		                                  TitledBorder.TOP, 
        		                                  null,
        		                                  new Color(0, 0, 0)));
        panelBackShape.add(checkBackShape, "flowx,cell 0 0 5 1");
        checkBackShape.setActionCommand(BACK);
        checkBackShape.addActionListener(ah);
        checkBackShape.setEnabled(false);
        
        panelBackShape.add(checkBackShapeResin, "cell 5 0,alignx right");
        checkBackShapeResin.setHorizontalTextPosition(SwingConstants.LEFT);
        checkBackShapeResin.setEnabled(false);
        
        panelBackShape.add(labelBackShape, "cell 0 1,alignx left");
        panelBackShape.add(comboBackShape, "cell 1 1,growx");
        comboBackShape.addItem(new ComboItem("Rectangle", ShapeType.RECTANGLE));
        comboBackShape.addItem(new ComboItem("Ellipse"  , ShapeType.ELLIPSE));
        comboBackShape.addItem(new ComboItem("RoundRect", ShapeType.ROUND_RECT));
        comboBackShape.addItem(new ComboItem("Pie"      , ShapeType.PIE));
        comboBackShape.addItem(new ComboItem("Chord"    , ShapeType.CHORD));
        comboBackShape.setEnabled(false);

        panelBackShape.add(labelBackShapeL, "flowx,cell 2 1,alignx right");
        panelBackShape.add(spinnerBackShapeL, "cell 2 1,alignx right");
        spinnerBackShapeL.setEditor(new JSpinner.NumberEditor(spinnerBackShapeL,"#"));
        spinnerBackShapeL.setEnabled(false);

        panelBackShape.add(labelBackShapeT, "flowx,cell 3 1,alignx right");
        panelBackShape.add(spinnerBackShapeT, "cell 3 1,alignx right");
        spinnerBackShapeT.setEditor(new JSpinner.NumberEditor(spinnerBackShapeT,"#"));
        spinnerBackShapeT.setEnabled(false);

        panelBackShape.add(labelBackShapeR, "flowx,cell 4 1,alignx right");
        panelBackShape.add(spinnerBackShapeR, "cell 4 1,alignx right");
        spinnerBackShapeR.setEditor(new JSpinner.NumberEditor(spinnerBackShapeR,"#"));
        spinnerBackShapeR.setEnabled(false);

        panelBackShape.add(labelBackShapeB, "flowx,cell 5 1,alignx right");
        panelBackShape.add(spinnerBackShapeB, "cell 5 1,alignx right");
        spinnerBackShapeB.setEditor(new JSpinner.NumberEditor(spinnerBackShapeB,"#"));
        spinnerBackShapeB.setEnabled(false);
        
        panelBackShape.add(labelBackShapeOutline, "cell 0 2,alignx left");
        panelBackShape.add(comboBackShapeOutline, "cell 1 2,growx");
        comboBackShapeOutline.addItem(new ColorCombo("Red",     Color.red));     
        comboBackShapeOutline.addItem(new ColorCombo("Green",   Color.green));      
        comboBackShapeOutline.addItem(new ColorCombo("Blue",    Color.blue));       
        comboBackShapeOutline.addItem(new ColorCombo("Cyan",    Color.cyan));        
        comboBackShapeOutline.addItem(new ColorCombo("Magenta", Color.magenta));  
        comboBackShapeOutline.addItem(new ColorCombo("Yellow",  Color.yellow));    
        comboBackShapeOutline.addItem(new ColorCombo("White",   Color.white));      
        comboBackShapeOutline.addItem(new ColorCombo("Black",   Color.black));
        comboBackShapeOutline.setEnabled(false);
        
        panelBackShape.add(labelBackShapeFill, "cell 2 2,alignx right");
        panelBackShape.add(comboBackShapeFill, "cell 3 2,growx");
        comboBackShapeFill.addItem(new ColorCombo("Red",     Color.red));     
        comboBackShapeFill.addItem(new ColorCombo("Green",   Color.green));      
        comboBackShapeFill.addItem(new ColorCombo("Blue",    Color.blue));       
        comboBackShapeFill.addItem(new ColorCombo("Cyan",    Color.cyan));        
        comboBackShapeFill.addItem(new ColorCombo("Magenta", Color.magenta));  
        comboBackShapeFill.addItem(new ColorCombo("Yellow",  Color.yellow));    
        comboBackShapeFill.addItem(new ColorCombo("White",   Color.white));      
        comboBackShapeFill.addItem(new ColorCombo("Black",   Color.black));    
        comboBackShapeFill.addItem(new ColorCombo("Transparent", TRANSPARENT));   
        comboBackShapeFill.setSelectedIndex(comboBackShapeFill.getItemCount() - 1);
        comboBackShapeFill.setEnabled(false);
        
        panelBackShape.add(labelBackShapeWidth, "flowx,cell 4 2,alignx right");
        panelBackShape.add(spinnerBackShapeWidth, "cell 4 2,alignx right");
        spinnerBackShapeWidth.setEnabled(false);
        
        //===== Back Line =====
        tabBack.add(panelBackLine, "cell 0 2,grow");
        panelBackLine.setLayout(new MigLayout("", "[][33.00:n][][][33.00:n][57.00][][grow][grow]", "[][][]"));
        panelBackLine.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
        		                                 "",
        		                                 TitledBorder.LEADING, 
        		                                 TitledBorder.TOP, 
        		                                 null,
        		                                 new Color(0, 0, 0)));
        panelBackLine.add(checkBackLine, "flowx,cell 0 0 8 1");
        checkBackLine.setActionCommand(BACK);
        checkBackLine.addActionListener(ah);
        checkBackLine.setEnabled(false);

        panelBackLine.add(checkBackLineResin, "cell 8 0,alignx right");
        checkBackLineResin.setHorizontalTextPosition(SwingConstants.LEFT);
        checkBackLineResin.setEnabled(false);

        panelBackLine.add(labelBackLine, "cell 0 1");
        panelBackLine.add(labelBackLineColour, "flowx,cell 1 1 4 1");
        panelBackLine.add(comboBackLineColour, "cell 1 1 4 1,growx");
        comboBackLineColour.addItem(new ColorCombo("Red",     Color.red));     
        comboBackLineColour.addItem(new ColorCombo("Green",   Color.green));    
        comboBackLineColour.addItem(new ColorCombo("Blue",    Color.blue));     
        comboBackLineColour.addItem(new ColorCombo("Cyan",    Color.cyan));      
        comboBackLineColour.addItem(new ColorCombo("Magenta", Color.magenta)); 
        comboBackLineColour.addItem(new ColorCombo("Yellow",  Color.yellow));  
        comboBackLineColour.addItem(new ColorCombo("White",   Color.white));    
        comboBackLineColour.addItem(new ColorCombo("Black",   Color.black));   
        comboBackLineColour.setEnabled(false);
        
        panelBackLine.add(labelBackLineWidth, "cell 6 1");
        spinnerBackLineWidth.setEnabled(false);
        panelBackLine.add(spinnerBackLineWidth, "cell 7 1,growx");
        
        panelBackLine.add(labelBackLineStart, "cell 0 2");
        panelBackLine.add(labelBackLineStartX, "flowx,cell 1 2 3 1");
        panelBackLine.add(spinnerBackLineStartX, "cell 1 2 3 1,growx");
        spinnerBackLineStartX.setEditor(new JSpinner.NumberEditor(spinnerBackLineStartX,"#"));
        spinnerBackLineStartX.setEnabled(false);

        panelBackLine.add(labelBackLineStartY, "flowx,cell 4 2 2 1");
        panelBackLine.add(spinnerBackLineStartY, "cell 4 2 2 1,growx");
        spinnerBackLineStartY.setEditor(new JSpinner.NumberEditor(spinnerBackLineStartY,"#"));
        spinnerBackLineStartY.setEnabled(false);
        
        panelBackLine.add(labelBackLineEnd, "cell 6 2");
        panelBackLine.add(labelBackLineEndX, "flowx,cell 7 2");
        panelBackLine.add(spinnerBackLineEndX, "cell 7 2,growx");
        spinnerBackLineEndX.setEditor(new JSpinner.NumberEditor(spinnerBackLineEndX,"#"));
        spinnerBackLineEndX.setEnabled(false);

        panelBackLine.add(labelBackLineEndY, "flowx,cell 8 2");
        panelBackLine.add(spinnerBackLineEndY, "cell 8 2,growx");
        spinnerBackLineEndY.setEditor(new JSpinner.NumberEditor(spinnerBackLineEndY,"#"));
        spinnerBackLineEndY.setEnabled(false);

        //===== Back Image =====
        tabBack.add(panelBackImage, "cell 0 3,grow");
        panelBackImage.setLayout(new MigLayout("", "[20%][20%][20%][20%][20%][]", "[][][]"));
        panelBackImage.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
                                                  "",
                		                          TitledBorder.LEADING, 
                                                  TitledBorder.TOP, 
                                                  null,
        		                                  new Color(0, 0, 0)));
        panelBackImage.add(checkBackImage, "flowx,cell 0 0 5 1");
        checkBackImage.setActionCommand(BACK);
        checkBackImage.addActionListener(ah);
        checkBackImage.setEnabled(false);

        panelBackImage.add(checkBackImageResin, "cell 5 0");
        checkBackImageResin.setHorizontalTextPosition(SwingConstants.LEFT);
        checkBackImageResin.setEnabled(false);
        
        panelBackImage.add(labelBackImage, "cell 0 1,alignx left");
        panelBackImage.add(textBackImage, "cell 1 1 4 1,growx");
        textBackImage.setEnabled(false);

        panelBackImage.add(btnBackImage, "cell 5 1");
        btnBackImage.setActionCommand(BACKIMAGE);
        btnBackImage.addActionListener(ah);
        btnBackImage.setEnabled(false);
        
        panelBackImage.add(labelBackImagePosition, "cell 0 2");
        panelBackImage.add(labelBackImageX, "flowx,cell 1 2");
        panelBackImage.add(spinnerBackImageX, "cell 1 2,growx");
        spinnerBackImageX.setEditor(new JSpinner.NumberEditor(spinnerBackImageX,"#"));
        spinnerBackImageX.setEnabled(false);

        panelBackImage.add(labelBackImageY, "flowx,cell 2 2");
        panelBackImage.add(spinnerBackImageY, "cell 2 2,growx");
        spinnerBackImageY.setEditor(new JSpinner.NumberEditor(spinnerBackImageY,"#"));
        spinnerBackImageY.setEnabled(false);

        panelBackImage.add(labelBackImageP1, "flowx,cell 3 2");
        panelBackImage.add(spinnerBackImageP1, "cell 3 2,growx");
        spinnerBackImageP1.setEditor(new JSpinner.NumberEditor(spinnerBackImageP1,"#"));
        spinnerBackImageP1.setEnabled(false);

        panelBackImage.add(labelBackImageP2, "flowx,cell 4 2");
        panelBackImage.add(spinnerBackImageP2, "cell 4 2,growx");
        spinnerBackImageP2.setEditor(new JSpinner.NumberEditor(spinnerBackImageP2,"#"));
        spinnerBackImageP2.setEnabled(false);

        panelPrintDemo.add(btnPrinterPrefs, "flowx,cell 0 3");
        btnPrinterPrefs.setActionCommand(PRINTPREFS);
        btnPrinterPrefs.addActionListener(ah);
        checkNativePrint.setSelected(true);
        
        panelPrintDemo.add(checkNativePrint, "cell 1 3");
        
        //===== Print Demo Button =====
        panelPrintDemo.add(btnPrint, "cell 2 3 2 1,alignx right");
        btnPrint.setActionCommand(PRINT);
        btnPrint.addActionListener(ah);
    }

    //====================================================================================

	@SuppressWarnings("serial")
	class PrintException extends Exception {

		public String ErrorString;
		public int Value;
		public PrintException(String error, int value) {
			ErrorString = error;
			Value = value;
		}
	}

    //====================================================================================

	void Init(HANDLE handle, SDKlib sdk) {
		tabbedPane.addTab("Print Demo", null, panelPrintDemo, null);
    	this.hSession = handle;
    	this.SDK = sdk;

    	spinnerFrontTextX.setModel(new SpinnerNumberModel(FRONT_TEXT_X, 0, MAX_X_COORD, 1));
    	spinnerFrontShapeL.setModel(new SpinnerNumberModel(FRONT_SHAPE_L, 0, MAX_X_COORD, 1));
    	spinnerFrontShapeR.setModel(new SpinnerNumberModel(FRONT_SHAPE_R, 0, MAX_X_COORD, 1));
    	spinnerFrontLineStartX.setModel(new SpinnerNumberModel(FRONT_LINE_START_X, 0, MAX_X_COORD, 1));
    	spinnerFrontLineEndX.setModel(new SpinnerNumberModel(FRONT_LINE_END_X, 0, MAX_X_COORD, 1));
    	spinnerFrontImageX.setModel(new SpinnerNumberModel(FRONT_IMAGE_X, 0, MAX_X_COORD, 1));
    	spinnerFrontImageP1.setModel(new SpinnerNumberModel(FRONT_IMAGE_P1, 0, MAX_CARD_LENGTH, 1));
    	spinnerBackTextX.setModel(new SpinnerNumberModel(BACK_TEXT_X, 0, MAX_X_COORD, 1));
    	spinnerBackShapeL.setModel(new SpinnerNumberModel(BACK_SHAPE_L, 0, MAX_X_COORD, 1));
    	spinnerBackShapeR.setModel(new SpinnerNumberModel(BACK_SHAPE_R, 0, MAX_X_COORD, 1));
    	spinnerBackLineStartX.setModel(new SpinnerNumberModel(BACK_LINE_START_X, 0, MAX_X_COORD, 1));
    	spinnerBackLineEndX.setModel(new SpinnerNumberModel(BACK_LINE_END_X, 0, MAX_X_COORD, 1));
    	spinnerBackImageX.setModel(new SpinnerNumberModel(BACK_IMAGE_X, 0, MAX_X_COORD, 1));
    	spinnerBackImageP1.setModel(new SpinnerNumberModel(BACK_IMAGE_P1, 0, MAX_CARD_LENGTH, 1));
	}
	
    //====================================================================================

	private void CardFrontChecked() {
		Boolean bControl = checkCardFront.isSelected();
		
		checkFrontText.setEnabled(bControl);
		checkFrontShape.setEnabled(bControl);
		checkFrontLine.setEnabled(bControl);
		checkFrontImage.setEnabled(bControl);
		checkMagData.setEnabled(bControl);
		btnPrint.setEnabled(bControl || checkCardBack.isSelected());

		bControl = checkCardFront.isSelected() && checkFrontText.isSelected();
		textFrontText.setEnabled(bControl);
		comboFrontTextColour.setEnabled(bControl);
		spinnerFrontTextSize.setEnabled(bControl);
		checkFrontBold.setEnabled(bControl);
		checkFrontItalic.setEnabled(bControl);
		checkFrontUnderline.setEnabled(bControl);
		checkFrontStrike.setEnabled(bControl);
		spinnerFrontTextX.setEnabled(bControl);
		spinnerFrontTextY.setEnabled(bControl);
		checkFrontTextResin.setEnabled(bControl);

		bControl = checkCardFront.isSelected() && checkFrontShape.isSelected();
		comboFrontShape.setEnabled(bControl);
		comboFrontShapeOutline.setEnabled(bControl);
		spinnerFrontShapeWidth.setEnabled(bControl);
		comboFrontShapeFill.setEnabled(bControl);
		spinnerFrontShapeL.setEnabled(bControl);
		spinnerFrontShapeT.setEnabled(bControl);
		spinnerFrontShapeR.setEnabled(bControl);
		spinnerFrontShapeB.setEnabled(bControl);
		checkFrontShapeResin.setEnabled(bControl);

		bControl = checkCardFront.isSelected() && checkFrontLine.isSelected();
		comboFrontLineColour.setEnabled(bControl);
		spinnerFrontLineWidth.setEnabled(bControl);
		spinnerFrontLineStartX.setEnabled(bControl);
		spinnerFrontLineStartY.setEnabled(bControl);
		spinnerFrontLineEndX.setEnabled(bControl);
		spinnerFrontLineEndY.setEnabled(bControl);
		checkFrontLineResin.setEnabled(bControl);

		bControl = checkCardFront.isSelected() && checkFrontImage.isSelected();
		spinnerFrontImageX.setEnabled(bControl);
		spinnerFrontImageY.setEnabled(bControl);
		spinnerFrontImageP1.setEnabled(bControl);
		spinnerFrontImageP2.setEnabled(bControl);
		textFrontImage.setEnabled(bControl);
		btnFrontImage.setEnabled(bControl);
		checkFrontImageResin.setEnabled(bControl);
		
		bControl = checkCardFront.isSelected() && checkMagData.isSelected();
		labelTrack1.setEnabled(bControl);
		textMag1Data.setEnabled(bControl);
		labelTrack2.setEnabled(bControl);
		textMag2Data.setEnabled(bControl);
		labelTrack3.setEnabled(bControl);
		textMag3Data.setEnabled(bControl);
	}

	//------------------------------------------------------------------------------------

	private void CardBackChecked() {
		Boolean bControl = checkCardBack.isSelected();

		checkBackText.setEnabled(bControl);
		checkBackLine.setEnabled(bControl);
		checkBackShape.setEnabled(bControl);
		checkBackImage.setEnabled(bControl);
		btnPrint.setEnabled(bControl || checkCardFront.isSelected());

		bControl = checkCardBack.isSelected() && checkBackText.isSelected();
		textBackText.setEnabled(bControl);
		comboBackTextColour.setEnabled(bControl);
		spinnerBackTextSize.setEnabled(bControl);
		checkBackBold.setEnabled(bControl);
		checkBackItalic.setEnabled(bControl);
		checkBackUnderline.setEnabled(bControl);
		checkBackStrike.setEnabled(bControl);
		spinnerBackTextX.setEnabled(bControl);
		spinnerBackTextY.setEnabled(bControl);
		checkBackTextResin.setEnabled(bControl);

		bControl = checkCardBack.isSelected() && checkBackShape.isSelected();
		comboBackShape.setEnabled(bControl);
		comboBackShapeOutline.setEnabled(bControl);
		spinnerBackShapeWidth.setEnabled(bControl);
		comboBackShapeFill.setEnabled(bControl);
		spinnerBackShapeL.setEnabled(bControl);
		spinnerBackShapeT.setEnabled(bControl);
		spinnerBackShapeR.setEnabled(bControl);
		spinnerBackShapeB.setEnabled(bControl);
		checkBackShapeResin.setEnabled(bControl);
		
		bControl = checkCardBack.isSelected() && checkBackLine.isSelected();
		comboBackLineColour.setEnabled(bControl);
		spinnerBackLineWidth.setEnabled(bControl);
        checkBackLineResin.setEnabled(bControl);
        spinnerBackLineStartX.setEnabled(bControl);
        spinnerBackLineStartY.setEnabled(bControl);
        spinnerBackLineEndX.setEnabled(bControl);
        spinnerBackLineEndY.setEnabled(bControl);

		bControl = checkCardBack.isSelected() && checkBackImage.isSelected();
		spinnerBackImageX.setEnabled(bControl);
		spinnerBackImageY.setEnabled(bControl);
		spinnerBackImageP1.setEnabled(bControl);
		spinnerBackImageP2.setEnabled(bControl);
		textBackImage.setEnabled(bControl);
		btnBackImage.setEnabled(bControl);
		checkBackImageResin.setEnabled(bControl);
	}
	
    //====================================================================================

	private String GetFilename() {
        // Displays an OpenFileDialog so the user can select an image file
		String result = "";
		JFileChooser db = new JFileChooser();
		FileNameExtensionFilter ft = new FileNameExtensionFilter("Image Files (*.bmp;*.jpg;*.png;*.tif)", "bmp", "jpg", "png", "tif");
		db.addChoosableFileFilter(ft);

		int rVal = db.showOpenDialog(null);
		if (rVal == JFileChooser.APPROVE_OPTION) {
			result = db.getSelectedFile().getAbsolutePath();
        }
		
		return result;
    }

	private void FrontImageFilenameClicked() {
		textFrontImage.setText(GetFilename());
    }

	private void BackImageFilenameClicked() {
		textBackImage.setText(GetFilename());
    }

    //====================================================================================

    private boolean FrontResin() {
		return (   checkFrontTextResin.isSelected()
                || checkFrontShapeResin.isSelected()
                || checkFrontLineResin.isSelected()
                || checkFrontImageResin.isSelected());
	}

    private boolean BackResin() {
		return (   checkBackTextResin.isSelected()
                || checkBackShapeResin.isSelected()
                || checkBackLineResin.isSelected()
                || checkBackImageResin.isSelected());
	}

    //====================================================================================

	private final float INCH = 72;
	private float scale = ((2.125f * INCH) / 642);

    void NativePrintText(Graphics2D g2d, 
    					 Color      colour,
    					 int        size,
    					 boolean    bold,
    					 boolean    italic,
    					 boolean    underline,
    					 boolean    strikeout,
    					 int        textX,
    					 int        textY,
    					 String     text)
    {
        //Define the font
        int fontStyle = Font.PLAIN;
		if (bold)      fontStyle |= FontStyle.BOLD;
		if (italic)    fontStyle |= FontStyle.ITALIC;
		if (underline) fontStyle |= FontStyle.UNDERLINE;
		if (strikeout) fontStyle |= FontStyle.STRIKEOUT;
		
	    g2d.setFont(new Font("Comic Sans MS", fontStyle, size));
		
		g2d.setColor(colour);

		g2d.drawString(text + " (Native)",  textX, textY);
    }
    
    void NativePrintShape(Graphics2D g2d, 
    					  byte       shape,
    					  Color      pen,
    					  int        penwidth,
    					  Color      brush,
    					  int        x,
    					  int        y,
    					  int        right,
    					  int        bottom)
    {
        int width  = right  - x;
        int height = bottom - y;

		g2d.setStroke(new BasicStroke(((Number)penwidth).floatValue()));
		g2d.setColor(brush);
		
		switch (shape) {
        case ShapeType.RECTANGLE:  
            if (brush != TRANSPARENT) {
                g2d.fillRect(x, y, width, height);
            }
            g2d.setColor(pen);
            g2d.drawRect(x, y, width, height);
        	break;

        case ShapeType.ELLIPSE:    
            if (brush != TRANSPARENT) {
            	g2d.fillOval(x, y, width, height);
            }
            g2d.setColor(pen);
            g2d.draw(new Ellipse2D.Double(x, y, width, height));
        	break;
        	
        case ShapeType.ROUND_RECT:
            if (brush != TRANSPARENT) {
            	g2d.fillRoundRect(x, y, width, height, 50, 50);
            }
            g2d.setColor(pen);
            g2d.drawRoundRect(x, y, width, height, 50, 50);
        	break;

        //case ShapeType.PIE:        g2d.DrawPie( 45, 60); break;
        //case ShapeType.CHORD:      g2d.DrawArc( 45, 60); break;
        }
    }
    
    void NativePrintLine(Graphics2D g2d, 
    					 Color      colour,
    					 float      width,
    					 int        startX,
    					 int        startY,
    					 int        endX,
    					 int        endY)
    {
		g2d.setColor(colour);
		g2d.setStroke(new BasicStroke(width));
		g2d.drawLine(startX, startY, endX, endY);
    }

    void NativePrintImage(Graphics2D g2d, 
    					  String     filename,
    					  int        x,
    					  int        y,
    					  int        p1,
    					  int        p2)
    {
		BufferedImage image = null;
		try {
			image = ImageIO.read(new File(filename));
		} 
		catch (IOException e) {
			e.printStackTrace();
		}
		
		int width  = image.getWidth();
		int height = image.getHeight();
        if (p1 == 0)
        {
            //No scaling or constraining - Use original size of image
        }
        else if (p2 == 0)
        {
            //Scaling - Modify image dimensions by scaling with the given percentage
	        //(p1), while maintaining the aspect ratio
            width  = (width  * p1) / 100;
            height = (height * p1) / 100;
        }
        else
        {
            //Constraining - Restrict the image to the given rectangle, ignoring aspect ratio
            //(p1 = new width, p2 = new height)
            width  = p1;
            height = p2;
        }
		g2d.drawImage(image, x, y, width, height, null);
    }
    
    //------------------------------------------------------------------------------------

    void PrintCard_Front(Graphics g, PageFormat pf)
    {
    	Graphics2D g2d = (Graphics2D)g;

    	g2d.setColor(Color.white);
        g2d.fillRect(0, 0, (int)pf.getWidth(), (int)pf.getHeight());

    	if (checkFrontText.isSelected()) {
    		NativePrintText(g2d, 
    						((ColorCombo)comboFrontTextColour.getSelectedItem()).getValue(),
    						(int)spinnerFrontTextSize.getValue(),
    						checkFrontBold.isSelected(),
    						checkFrontItalic.isSelected(),
    						checkFrontUnderline.isSelected(),
    						checkFrontStrike.isSelected(),
    						3, //(int)spinnerFrontTextX.getValue(),
    						23, //(int)spinnerFrontTextY.getValue(),
    						textFrontText.getText());
    	}

    	g2d.scale(scale, scale);

    	if (checkFrontShape.isSelected()) {
    		NativePrintShape(g2d, 
    						 ((ComboItem)comboFrontShape.getSelectedItem()).getValue(),
    						 ((ColorCombo)comboFrontShapeOutline.getSelectedItem()).getValue(),
    						 (int)spinnerFrontShapeWidth.getValue(),
    						 ((ColorCombo)comboFrontShapeFill.getSelectedItem()).getValue(),
    						 (int)spinnerFrontShapeL.getValue(),
    						 (int)spinnerFrontShapeT.getValue(),
    						 (int)spinnerFrontShapeR.getValue(),
    						 (int)spinnerFrontShapeB.getValue());
        }

    	if (checkFrontLine.isSelected()) {
    		NativePrintLine(g2d,
					((ColorCombo)comboFrontLineColour.getSelectedItem()).getValue(),
					((Number)spinnerFrontLineWidth.getValue()).floatValue(),
					(int)spinnerFrontLineStartX.getValue(), 
					(int)spinnerFrontLineStartY.getValue(), 
					(int)spinnerFrontLineEndX.getValue(), 
					(int)spinnerFrontLineEndY.getValue());
    	}

        //Has an image file been selected?
		if (checkFrontImage.isSelected()
		&& (textFrontImage.getText().length() != 0)) {
	       	NativePrintImage(g2d, 
	       					 textFrontImage.getText(),
	       					(int)spinnerFrontImageX.getValue(),
	       					(int)spinnerFrontImageY.getValue(),
	       					(int)spinnerFrontImageP1.getValue(),
	       					(int)spinnerFrontImageP2.getValue());
        }
    }

    //------------------------------------------------------------------------------------

    void PrintCard_Back(Graphics g, PageFormat pf)
    {
    	Graphics2D g2d = (Graphics2D)g;
        g2d.translate(pf.getImageableX(), pf.getImageableY()); 
    	
    	if (checkBackText.isSelected()) {
            //Define the font
            int fontStyle = Font.PLAIN;
    		if (checkBackBold.isSelected())      fontStyle |= FontStyle.BOLD;
    		if (checkBackItalic.isSelected())    fontStyle |= FontStyle.ITALIC;
    		if (checkBackUnderline.isSelected()) fontStyle |= FontStyle.UNDERLINE;
    		if (checkBackStrike.isSelected())    fontStyle |= FontStyle.STRIKEOUT;
    		g2d.setFont(new Font("Comic Sans MS", fontStyle, (int)spinnerBackTextSize.getValue()));

    		g2d.setColor(((ColorCombo)comboBackTextColour.getSelectedItem()).getValue());
    		g2d.drawString(textBackText.getText(), (int)spinnerBackTextX.getValue(), (int)spinnerBackTextY.getValue());
        }

    	g2d.scale(scale, scale);

    	if (checkBackShape.isSelected()) {
    		NativePrintText(g2d, 
					((ColorCombo)comboBackTextColour.getSelectedItem()).getValue(),
					(int)spinnerBackTextSize.getValue(),
					checkBackBold.isSelected(),
					checkBackItalic.isSelected(),
					checkBackUnderline.isSelected(),
					checkBackStrike.isSelected(),
					(int)spinnerBackTextX.getValue(),
					(int)spinnerBackTextY.getValue(),
					textBackText.getText());
        }

    	if (checkBackLine.isSelected()) {
    		NativePrintLine(g2d,
					((ColorCombo)comboBackLineColour.getSelectedItem()).getValue(),
					((Number)spinnerBackLineWidth.getValue()).floatValue(),
					(int)spinnerBackLineStartX.getValue(), 
					(int)spinnerBackLineStartY.getValue(), 
					(int)spinnerBackLineEndX.getValue(), 
					(int)spinnerBackLineEndY.getValue());
        }

		if (checkBackImage.isSelected()
		&& (textBackImage.getText().length() != 0)) {
	       	NativePrintImage(g2d, 
  					 textFrontImage.getText(),
  					(int)spinnerBackImageX.getValue(),
  					(int)spinnerBackImageY.getValue(),
  					(int)spinnerBackImageP1.getValue(),
  					(int)spinnerBackImageP2.getValue());
        }
    }

    //------------------------------------------------------------------------------------

	@Override
	public int print(Graphics g, PageFormat pf, int pageNum) throws PrinterException {
	    switch (pageNum) {
	    case 0:  
	    	if (checkCardFront.isSelected()) {
                PrintCard_Front(g, pf);
                if (checkCardBack.isSelected()) {
                    pageNum = 1;
                }
            }
            else {
                PrintCard_Back(g, pf);
            }
	    	return PAGE_EXISTS;
	    	
	    case 1:
	    	if (checkCardBack.isSelected()) {
                PrintCard_Back(g, pf);
    	    	return PAGE_EXISTS;
            }
	    	else {
		    	return NO_SUCH_PAGE;
	    	}
	    	
	    default:
	      return NO_SUCH_PAGE;
	    }
	}

    //------------------------------------------------------------------------------------

	private void PrintUsingNative() {
		Paper p = new Paper();
    	p.setSize(2.125 * INCH, 3.375 * INCH); //NB Paper MUST be defined in portrait orientation
    	p.setImageableArea(0, 0, p.getWidth(), p.getHeight());

    	PageFormat pf = new PageFormat();
    	pf.setOrientation(PageFormat.LANDSCAPE);
    	pf.setPaper(p);
    	Printer.pj.setPrintable(this, pf);
    	
    	//@@@@ Update the devmode @@@@
//    	byte sdkReturn = SDK.ID_UpdateDevmode(hSession, Printer.pj.);
//        if (sdkReturn != Return.SUCCESS)
//        {
//        	  DisplayError("UpdateDevMode", sdkReturn);
//            return;
//        }

        try {
        	Printer.pj.print();
        }
        catch (PrinterException e) {
        	e.printStackTrace();
        }

    }
    
	//------------------------------------------------------------------------------------

    private void PrintButtonClicked() {
    	CursorWait();

		if (checkNativePrint.isSelected())
		{
            PrintUsingNative();
		}

		else {
			byte sdkReturn;
			
			try {
/*    		
				************************************************************************************	
				* Currently, the demo app uses the driver settings as configured under the Driver1 *
				* and Driver2 tabs.  Should the developer wish to control this dependent on the    *
				* print selections, and modify these with code, a process such as shown here in    *
				* could be used.                                                                   *
				************************************************************************************	
				//Call SDK function to READ the print settings for the card so that they can be saved
				PrintSettings OldPS = new PrintSettings();
				sdkReturn = SDK.ID_PrintSettings(hSession, Action.READ, OldPS);
				if (sdkReturn != Return.SUCCESS) {
					throw new PrintException("OldPrintSettings", sdkReturn);
				}
				PrintSettings PS = OldPS;
		
				//Determine which sides of the card need to be printed
				if (checkCardFront.isSelected()
				&&  checkCardBack.isSelected()) {
					PS.Duplex = Duplex.BothSides;
				}
				else if (checkCardFront.isSelected()) {
					PS.Duplex = Duplex.FrontOnly;
				}
				else {
					PS.Duplex = Duplex.BackOnly;
				}
		
				//Change the print settings for the card
				sdkReturn = SDK.ID_PrintSettings(hSession, Action.WRITE, PS);
				if (sdkReturn != Return.SUCCESS) {
					throw new PrintException("WritePrintSettings", sdkReturn);
				}
*/
				TextDef  TextDef  = SDK.new TextDef();
				ShapeDef ShapeDef = SDK.new ShapeDef();
				LineDef  LineDef  = SDK.new LineDef();
				
				//Is there a Front to be printed?
				if (checkCardFront.isSelected()) {
					//Initialise Front Canvas
					IntByReference FrontDC = new IntByReference();
					sdkReturn = SDK.ID_CanvasInit(hSession, FrontDC, Canvas.FRONT);
					if (sdkReturn != Return.SUCCESS) {
						throw new PrintException("CanvasInitFront", sdkReturn);
					}
		
					if (FrontResin()) {
						IntByReference FrontResinDC = new IntByReference();
						sdkReturn = SDK.ID_CanvasInit(hSession, FrontResinDC, Canvas.FRONT_RESIN);
						if (sdkReturn != Return.SUCCESS) {
							throw new PrintException("CanvasInitFrontResin", sdkReturn);
						}
					}
		
					if (checkFrontText.isSelected()) {
						//Front Text....
						//Define the font
						TextDef.fontName   = "Comic Sans MS";
						TextDef.fontSize   = (int)spinnerFrontTextSize.getValue();
						TextDef.fontColour = ((ColorCombo)comboFrontTextColour.getSelectedItem()).getValue();
						TextDef.fontStyle  = 0;
						if (checkFrontBold.isSelected())      TextDef.fontStyle |= FontStyle.BOLD;
						if (checkFrontItalic.isSelected())    TextDef.fontStyle |= FontStyle.ITALIC;
						if (checkFrontUnderline.isSelected()) TextDef.fontStyle |= FontStyle.UNDERLINE;
						if (checkFrontStrike.isSelected())    TextDef.fontStyle |= FontStyle.STRIKEOUT;

						//Get the location and angle for the text
						TextDef.x = (int)spinnerFrontTextX.getValue();
						TextDef.y = (int)spinnerFrontTextY.getValue();
						TextDef.angle = 0;
			
						//Get the text to be drawn
						TextDef.text = textFrontText.getText();
			
						//Call the SDK function to draw the text on the canvas
				        byte canvas = checkFrontTextResin.isSelected() ? Canvas.FRONT_RESIN : Canvas.FRONT;
						sdkReturn = SDK.ID_DrawText(hSession, canvas, TextDef);
						if (sdkReturn != Return.SUCCESS) {
							throw new PrintException("DrawTextFront", sdkReturn);
						}
					}
		
					if (checkFrontShape.isSelected()) {
						//Front Shape...
						//Get the shape's definition
						ShapeDef.shape       = ((ComboItem)comboFrontShape.getSelectedItem()).getValue();
						ShapeDef.penColour   = ((ColorCombo)comboFrontShapeOutline.getSelectedItem()).getValue();
						ShapeDef.fillColour  = ((ColorCombo)comboFrontShapeFill.getSelectedItem()).getValue();
						ShapeDef.penWidth    = (int)spinnerFrontShapeWidth.getValue();
						ShapeDef.area.left   = (int)spinnerFrontShapeL.getValue();
						ShapeDef.area.top    = (int)spinnerFrontShapeT.getValue();
						ShapeDef.area.right  = (int)spinnerFrontShapeR.getValue();
						ShapeDef.area.bottom = (int)spinnerFrontShapeB.getValue();
			
						//Set up the specific parameters for given shapes.
						//For simplicity, these have been hard coded here rather than GUI selectable
						switch (ShapeDef.shape) {
						case ShapeType.ROUND_RECT:
							ShapeDef.p1 = 50;			// Corner Width
							ShapeDef.p2 = 50;			// Corner Height
							break;
						case ShapeType.PIE:
						case ShapeType.CHORD:
							ShapeDef.area.left   = 40;
							ShapeDef.area.top    = 20;
							ShapeDef.area.right  = 800;
							ShapeDef.area.bottom = 500;
							ShapeDef.p1			 = 0;	// Radial 1 X Co-ord
							ShapeDef.p2			 = 0;	// Radial 1 Y Co-ord
							ShapeDef.p3			 = 700;	// Radial 2 X Co-ord
							ShapeDef.p4			 = 115;	// Radial 2 Y Co-ord
							break;
						}
		
						//Call the SDK function to draw the shape on the canvas
				        byte canvas = checkFrontShapeResin.isSelected() ? Canvas.FRONT_RESIN : Canvas.FRONT;
						sdkReturn = SDK.ID_DrawShape(hSession, canvas, ShapeDef);
						if (sdkReturn != Return.SUCCESS) {
							throw new PrintException("DrawShapeFront", sdkReturn);
						}
					}
		
					if (checkFrontLine.isSelected()) {
						//Front Line...
						//Get the line's definition
						LineDef.colour  = ((ColorCombo)comboFrontLineColour.getSelectedItem()).getValue();
						LineDef.width   = (int)spinnerFrontLineWidth.getValue();
			
						//Get the line location
						LineDef.startX = (int)spinnerFrontLineStartX.getValue();
						LineDef.startY = (int)spinnerFrontLineStartY.getValue();
						LineDef.endX   = (int)spinnerFrontLineEndX.getValue();
						LineDef.endY   = (int)spinnerFrontLineEndY.getValue();
			
						//Call the SDK function to draw the line on the canvas
						byte canvas = checkFrontLineResin.isSelected() ? Canvas.FRONT_RESIN : Canvas.FRONT;
						sdkReturn = SDK.ID_DrawLine(hSession, canvas, LineDef);
						if (sdkReturn != Return.SUCCESS) {
							throw new PrintException("DrawLineFront", sdkReturn);
						}
					}
		
					//Has an image file been selected?
					if (checkFrontImage.isSelected()
					&& (textFrontImage.getText().length() != 0)) {
						//Front Image.......
						//Get the image boundaries
						ImageDef Image = new ImageDef();
						Image.x  = (int)spinnerFrontImageX.getValue();
						Image.y  = (int)spinnerFrontImageY.getValue();
						Image.p1 = (int)spinnerFrontImageP1.getValue();
						Image.p2 = (int)spinnerFrontImageP2.getValue();
		
						Image.filename = textFrontImage.getText();
		
						//Call the SDK function to draw the image on the canvas
				        byte canvas = checkFrontImageResin.isSelected() ? Canvas.FRONT_RESIN : Canvas.FRONT;
				       	sdkReturn = SDK.ID_DrawImage(hSession, canvas, Image);
						if (sdkReturn != Return.SUCCESS) {
							throw new PrintException("DrawImageFront", sdkReturn);
						}
					}

					if (checkMagData.isSelected()) {
						MagTextDef MagText = SDK.new MagTextDef();
						
						//===== Front Magnetic Data =====
						if (textMag1Data.getText().length() != 0) {
							MagText.track = 1;
							MagText.data  = textMag1Data.getText();

							//Call the SDK function to draw the image on the canvas
							sdkReturn = SDK.ID_DrawMagText(hSession, Canvas.FRONT, MagText);
							if (sdkReturn != Return.SUCCESS) {
								throw new PrintException("Mag1DataFront", sdkReturn);
							}
						}

						if (textMag2Data.getText().length() != 0) {
							MagText.track = 2;
							MagText.data  = textMag2Data.getText();

							//Call the SDK function to draw the image on the canvas
							sdkReturn = SDK.ID_DrawMagText(hSession, Canvas.FRONT, MagText);
							if (sdkReturn != Return.SUCCESS) {
								throw new PrintException("Mag2DataFront", sdkReturn);
							}
						}

						if (textMag3Data.getText().length() != 0) {
							MagText.track = 3;
							MagText.data  = textMag3Data.getText();

							//Call the SDK function to draw the image on the canvas
							sdkReturn = SDK.ID_DrawMagText(hSession, Canvas.FRONT, MagText);
							if (sdkReturn != Return.SUCCESS) {
								throw new PrintException("Mag3DataFront", sdkReturn);
							}
						}
					}
				}
		
				//-------------------------------------------------------------------
		
				//Is there a BACK to be printed?
				if (checkCardBack.isSelected()) {
/*
					***********************************************************************************	
					* Similarly, settings for the BACK of the card are defined under the Driver1 and  *
					* Driver 2 tabs.  This code block reads the settings to save them for restore     *
					* later, and modifies the colour settings according to the Print Demo tab         *
					* selections.                                                                     *
					***********************************************************************************	
					//READ the current settings for the BACK of the card
					CardSettings OldBack = new CardSettings();
					sdkReturn = SDK.ID_CardSettings(hSession, Action.READ, Side.BACK, OldBack);
					if (sdkReturn != Return.SUCCESS) {
						throw new PrintException("OldCardSettings", sdkReturn);
					}
					CardSettings CS = OldBack;

					//If colour is required, modify the card settings for the BACK of the card
					if ((((ColorCombo)comboBackTextColour.getSelectedItem()).getValue()   != Color.black)
					||  (((ColorCombo)comboBackShapeOutline.getSelectedItem()).getValue() != Color.black)
					||  (((ColorCombo)comboBackShapeFill.getSelectedItem()).getValue()    != Color.black)
					||  (((ColorCombo)comboBackLineColour.getSelectedItem()).getValue()   != Color.black)) {
						CS.ColourFormat = ColourFormat.YMCK;

						sdkReturn = SDK.ID_CardSettings(hSession, Action.WRITE, Side.BACK, CS);
						if (sdkReturn != Return.SUCCESS) {
							throw new PrintException("CardSettingsBack", sdkReturn);
						}
					}
*/
					//Initialise Rear Canvas
					IntByReference BackDC = new IntByReference();
					sdkReturn = SDK.ID_CanvasInit(hSession, BackDC, Canvas.BACK);
					if (sdkReturn != Return.SUCCESS) {
						throw new PrintException("CanvasInitBack", sdkReturn);
					}

					if (BackResin()) {
						IntByReference BackResinDC = new IntByReference();
						sdkReturn = SDK.ID_CanvasInit(hSession, BackResinDC, Canvas.BACK_RESIN);
						if (sdkReturn != Return.SUCCESS) {
							throw new PrintException("CanvasInitBackResin", sdkReturn);
						}
					}
		
					if (checkBackText.isSelected()) {
						//Back Text
						TextDef.fontName   = "Comic Sans MS";
						TextDef.fontSize   = (int)spinnerBackTextSize.getValue();
						TextDef.fontColour = ((ColorCombo)comboBackTextColour.getSelectedItem()).getValue();
						TextDef.fontStyle  = 0;
						if (checkBackBold.isSelected())      TextDef.fontStyle |= FontStyle.BOLD;
						if (checkBackItalic.isSelected())    TextDef.fontStyle |= FontStyle.ITALIC;
						if (checkBackUnderline.isSelected()) TextDef.fontStyle |= FontStyle.UNDERLINE;
						if (checkBackStrike.isSelected())    TextDef.fontStyle |= FontStyle.STRIKEOUT;
						TextDef.x = (int)spinnerBackTextX.getValue();
						TextDef.y = (int)spinnerBackTextY.getValue();
						TextDef.angle = 0;
			
						TextDef.text = textBackText.getText();

						byte canvas = checkBackTextResin.isSelected() ? Canvas.BACK_RESIN : Canvas.BACK;
						sdkReturn = SDK.ID_DrawText(hSession, canvas, TextDef);
						if (sdkReturn != Return.SUCCESS) {
							throw new PrintException("DrawTextback", sdkReturn);
						}
					}
		
					if (checkBackShape.isSelected()) {
						//Back Shape
						ShapeDef.shape       = ((ComboItem)comboBackShape.getSelectedItem()).getValue();
						ShapeDef.penColour   = ((ColorCombo)comboBackShapeOutline.getSelectedItem()).getValue();
						ShapeDef.fillColour  = ((ColorCombo)comboBackShapeFill.getSelectedItem()).getValue();
						ShapeDef.penWidth    = (int)spinnerBackShapeWidth.getValue();
						ShapeDef.area.left   = (int)spinnerBackShapeL.getValue();
						ShapeDef.area.top    = (int)spinnerBackShapeT.getValue();
						ShapeDef.area.right  = (int)spinnerBackShapeR.getValue();
						ShapeDef.area.bottom = (int)spinnerBackShapeB.getValue();
			 
						switch (ShapeDef.shape) {
						case ShapeType.ROUND_RECT:
							ShapeDef.p1 = 50;			// Corner Width
							ShapeDef.p2 = 50;			// Corner Height
							break;
						case ShapeType.PIE:
						case ShapeType.CHORD:
							ShapeDef.area.left   = 40;
							ShapeDef.area.top    = 20;
							ShapeDef.area.right  = 800;
							ShapeDef.area.bottom = 500;
							ShapeDef.p1			 = 0;	// Radial 1 X Co-ord
							ShapeDef.p2			 = 0;	// Radial 1 Y Co-ord
							ShapeDef.p3			 = 700;	// Radial 2 X Co-ord
							ShapeDef.p4			 = 115;	// Radial 2 Y Co-ord
							break;
						}
			
				        byte canvas = checkBackShapeResin.isSelected() ? Canvas.BACK_RESIN : Canvas.BACK;
				       	sdkReturn = SDK.ID_DrawShape(hSession, canvas, ShapeDef);
						if (sdkReturn != Return.SUCCESS) {
							throw new PrintException("DrawShapeBack", sdkReturn);
						}
					}
		
					if (checkBackLine.isSelected()) {
						//Back Line...
						//Get the line's definition
						LineDef.colour  = ((ColorCombo)comboBackLineColour.getSelectedItem()).getValue();
						LineDef.width   = (int)spinnerBackLineWidth.getValue();
			
						//Get the line location
						LineDef.startX = (int)spinnerBackLineStartX.getValue();
						LineDef.startY = (int)spinnerBackLineStartY.getValue();
						LineDef.endX   = (int)spinnerBackLineEndX.getValue();
						LineDef.endY   = (int)spinnerBackLineEndY.getValue();
			
						//Call the SDK function to draw the line on the canvas
				        byte canvas = checkBackLineResin.isSelected() ? Canvas.BACK_RESIN : Canvas.BACK;
				       	sdkReturn = SDK.ID_DrawLine(hSession, canvas, LineDef);
						if (sdkReturn != Return.SUCCESS) {
							throw new PrintException("DrawLineBack", sdkReturn);
						}
					}

					//Has an image file been selected?
					if (checkBackImage.isSelected()
					&& (textBackImage.getText().length() != 0)) {
						//Front Image.......
						//Get the image boundaries
						ImageDef Image = new ImageDef();
						Image.x  = (int)spinnerBackImageX.getValue();
						Image.y  = (int)spinnerBackImageY.getValue();
						Image.p1 = (int)spinnerBackImageP1.getValue();
						Image.p2 = (int)spinnerBackImageP2.getValue();
		
						Image.filename = textBackImage.getText();
		
						//Call the SDK function to draw the image on the canvas
				        byte canvas = checkBackImageResin.isSelected() ? Canvas.BACK_RESIN : Canvas.BACK;
				       	sdkReturn = SDK.ID_DrawImage(hSession, canvas, Image);
						if (sdkReturn != Return.SUCCESS) {
							throw new PrintException("DrawImageFront", sdkReturn);
						}
					}
				}
		
				//-------------------------------------------------------------------

				//Print the Card
				sdkReturn = SDK.ID_PrintCard(hSession);
				if (sdkReturn != Return.SUCCESS) {
					throw new PrintException("PrintCard", sdkReturn);
				}
		
				//Wait for the printing to complete
				sdkReturn = WaitForPrinterToFinish(hSession, SDK);
				if (sdkReturn != Return.SUCCESS) {
					throw new PrintException("PrintCardWait", sdkReturn);
				}
/*	
				**************************************************************************************
				* Restore the settings for the print job, and for the card BACK, as saved previously *
				**************************************************************************************
				//Restore Original Print Settings
				sdkReturn = SDK.ID_PrintSettings(hSession, Action.WRITE, OldPS);
				if (sdkReturn != Return.SUCCESS) {
					throw new PrintException("RestorePrintSettings", sdkReturn);
				}
		
				//Restore the Original Settings for the BACK of the Card
				sdkReturn = SDK.ID_CardSettings(hSession, Action.WRITE, Side.BACK, OldBack);
				if (sdkReturn != Return.SUCCESS) {
					throw new PrintException("RestoreBackSettings", sdkReturn);
				}
*/	    	
			} 

			catch (PrintException e) {
				if (checkCardFront.isSelected()) {
					SDK.ID_CanvasDelete(hSession, Canvas.FRONT);
					if (FrontResin()) {
						SDK.ID_CanvasDelete(hSession, Canvas.FRONT_RESIN);
					}
				}
				if (checkCardBack.isSelected()) {
					SDK.ID_CanvasDelete(hSession, Canvas.BACK);
					if (BackResin()) {
						SDK.ID_CanvasDelete(hSession, Canvas.BACK_RESIN);
					}
				}
				DisplayError(e.ErrorString, e.Value);
			} 
		}

		CursorDefault();
    }

    //====================================================================================

    void PrintPrefsClicked()
    {
		byte sdkReturn = SDK.ID_PrinterPrefs(hSession); 
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("PrinterPrefs", sdkReturn);
		}
    }
    
    //====================================================================================

    class ActionHandler implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			switch (e.getActionCommand()) {
			case FRONT:      CardFrontChecked();     	  break;
			case BACK:       CardBackChecked();      	  break;
			case FRONTIMAGE: FrontImageFilenameClicked(); break;
			case BACKIMAGE:  BackImageFilenameClicked();  break;
			case PRINT:      PrintButtonClicked();   	  break;
			case PRINTPREFS: PrintPrefsClicked();         break;
			}
		}
	}
}
