package DTCDemo;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.text.ParseException;

import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.AttributeSet;
import javax.print.attribute.HashAttributeSet;
import javax.print.attribute.standard.Media;
import javax.print.attribute.standard.MediaSize;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.PrinterName;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFormattedTextField;
import javax.swing.JFormattedTextField.AbstractFormatter;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.SpinnerNumberModel;
import javax.swing.UIManager;
import javax.swing.border.TitledBorder;
import javax.swing.text.DefaultFormatter;
import javax.swing.text.DefaultFormatterFactory;

import net.miginfocom.swing.MigLayout;
import SDK.SDKlib;
import SDK.SDKlib.Action;
import SDK.SDKlib.Area;
import SDK.SDKlib.CardSettings;
import SDK.SDKlib.ColourAdj;
import SDK.SDKlib.ColourAdj.*;
import SDK.SDKlib.ColourFormat;
import SDK.SDKlib.Duplex;
import SDK.SDKlib.HoloKote;
import SDK.SDKlib.HoloPatch;
import SDK.SDKlib.Orientation;
import SDK.SDKlib.PrintSettings;
import SDK.SDKlib.Return;
import SDK.SDKlib.Rotation;
import SDK.SDKlib.Side;

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

import javax.swing.SwingConstants;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;

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

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

public class Driver2 {
	static final int MAX_COPIES        = 99;
	static final int MAX_HOLOKOTE_MAP  = 0xFFFFFF;
	static final int MAX_HOLOPATCH     = 24;
	static final int DEFAULT_HOLOPATCH = 6;
	static final int MAX_HOLOKOTE_ID   = 12;

	private final String PRINT        = "PRINT";
	private final String CARD         = "CARD";
	private final String CSCHANGED    = "CSCHANGED";
	private final String HOLOKOTE     = "HOLOKOTE";
	private final String HKCHANGED    = "HKCHANGED";
	private final String HOLOPATCH    = "HOLOPATCH";
	private final String COLOURAREA   = "COLOURAREA";
	private final String CACHANGED    = "CACHANGED";
	private final String COLOURADJUST = "COLOURADJUST";
	private final String HKPREVIEW    = "HKPREVIEW";
	private final String RADIOGET     = "RADIOGET";
	private final String RADIOSET     = "RADIOSET";
	private final String CLEAR        = "CLEAR";

	private final ActionHandler ah = new ActionHandler();

	public static final JPanel panelDriver2 = new JPanel();

	private final JPanel panelAction = new JPanel();
	private final JLabel labelAction = new JLabel("Action:");
	private final JRadioButton rdbtnGet = new JRadioButton("Get");
	private final JRadioButton rdbtnSet = new JRadioButton("Set");
	private final ButtonGroup buttonGroup = new ButtonGroup();

	private final JPanel panelPrintSettings = new JPanel();
	private final JLabel labelPrintSides = new JLabel("Sides to Print");
	private final JComboBox<ComboItem> comboDuplex = new JComboBox<ComboItem>();
	private final JLabel labelCardSize = new JLabel("Card Size");
	private final JComboBox<MediaCombo> comboCardSize = new JComboBox<MediaCombo>();
	private final JLabel labelPrintCopies = new JLabel("Copies");
	private final JSpinner spinnerCopies = new JSpinner(new SpinnerNumberModel(1, 1, MAX_COPIES, 1));
	private final JButton btnPrintSettings = new JButton("Print Settings");

	private final JPanel panelCardSettings = new JPanel();
	private final JLabel labelCardSide = new JLabel("Side");
	private final JComboBox<ComboItem> comboCardSide = new JComboBox<ComboItem>();
	private final JLabel labelColourFormat = new JLabel("Colour Format");
	private final JComboBox<ComboItem> comboColourFormat = new JComboBox<ComboItem>();
	private final JLabel labelOrientation = new JLabel("Orientation");
	private final JComboBox<ComboItem> comboOrientation = new JComboBox<ComboItem>();
	private final JCheckBox checkOvercoat = new JCheckBox("Overcoat");
	private final JCheckBox checkRotate = new JCheckBox("Rotate");
	private final JButton btnCardSettings = new JButton("Card Settings");

	private final JPanel panelHoloKote = new JPanel();
	private final JLabel labelHoloKoteSide = new JLabel("Side");
	private final JComboBox<ComboItem> comboHoloKoteSide = new JComboBox<ComboItem>();
	private final JSpinner spinnerHoloKoteNo = new JSpinner(new SpinnerNumberModel(new Byte("0"),
			                                                                       new Byte("0"), 
			                                                                       new Byte((byte) MAX_HOLOKOTE_ID), 
			                                                                       new Byte("1")));
	private final JLabel labelHoloKoteMap = new JLabel("Map");
	private final JSpinner spinnerHoloKoteMap = new JSpinner(new SpinnerNumberModel(MAX_HOLOKOTE_MAP, 
	                                                                                0, 
	                                                                                MAX_HOLOKOTE_MAP, 
	                                                                                1));
	private final JLabel labelHoloKoteRotation = new JLabel("Rotation");
	private final JComboBox<ComboItem> comboHoloKoteRotation = new JComboBox<ComboItem>();
	private final JCheckBox checkUseLaminate = new JCheckBox("Use Laminate");
	private final JCheckBox checkNoCustomKey = new JCheckBox("No Custom Key");
	private final JButton btnHoloKote = new JButton("HoloKote");

	private final JPanel panelHoloPatch = new JPanel();
	private final JLabel labelPosition = new JLabel("Position");
	private final JSpinner spinnerHoloPatch = new JSpinner(new SpinnerNumberModel(new Byte((byte) DEFAULT_HOLOPATCH),
			                                                                      new Byte("0"), 
			                                                                      new Byte((byte) MAX_HOLOPATCH), 
			                                                                      new Byte("1")));
	private final JCheckBox checkColourHole = new JCheckBox("Colour Hole");
	private final JButton btnHoloPatch = new JButton("HoloPatch");

	private final JPanel panelColourAdjust = new JPanel();
	private final JPanel panelColourArea = new JPanel();
	private final JLabel labelSide = new JLabel("Side");
	private final JComboBox<ComboItem> comboColourAreaSide = new JComboBox<ComboItem>();
	private final JLabel labelCorrection = new JLabel("Correction");
	private final JButton btnColourArea = new JButton("Colour Area");
	private final JSpinner spinnerColourAreaL = new JSpinner(new SpinnerNumberModel(0, 0, maxXCoord, 1));
	private final JSpinner spinnerColourAreaW = new JSpinner(new SpinnerNumberModel(0, 0, maxCardLength, 1));
	private final JSpinner spinnerColourAreaB = new JSpinner(new SpinnerNumberModel(0, 0, MAX_Y_COORD, 1));
	private final JSpinner spinnerColourAreaH = new JSpinner(new SpinnerNumberModel(0, 0, MAX_CARD_HEIGHT, 1));
	private final JLabel labelID = new JLabel("ID");
	private final JButton btnColourAdjust = new JButton("Colour Adjust");
	private final JSpinner spinnerBlackRef = new JSpinner(new SpinnerNumberModel(ColourAdj.REF_BLACK_MIN, 
	                                                                             ColourAdj.REF_BLACK_MIN, 
	                                                                             ColourAdj.REF_BLACK_MAX, 
	                                                                             1));
	private final JSpinner spinnerWhiteRef = new JSpinner(new SpinnerNumberModel(ColourAdj.REF_WHITE_MIN, 
																				 ColourAdj.REF_WHITE_MIN, 
																				 ColourAdj.REF_WHITE_MAX, 
																				 1));
	private final JLabel labelBlackRef = new JLabel("Black Ref");
	private final JLabel labelWhiteRef = new JLabel("White Ref");
	private final JLabel labelIlluminant = new JLabel("Illuminant");
	private final JComboBox<ComboItem> comboIlluminant = new JComboBox<ComboItem>();
	private final JCheckBox checkDarkPicture = new JCheckBox("Dark Picture");
	private final JLabel labelContrast = new JLabel("Contrast");
	private final JSpinner spinnerColourAdjustRed   = new JSpinner(new SpinnerNumberModel(ColourAdj.RGB_GAMMA_MIN, 
																						  ColourAdj.RGB_GAMMA_MIN, 
																						  ColourAdj.RGB_GAMMA_MAX, 
																						  1));
	private final JSpinner spinnerColourAdjustBlue  = new JSpinner(new SpinnerNumberModel(ColourAdj.RGB_GAMMA_MIN, 
																						  ColourAdj.RGB_GAMMA_MIN, 
																						  ColourAdj.RGB_GAMMA_MAX, 
			  																			  1));
	private final JSpinner spinnerColourAdjustGreen = new JSpinner(new SpinnerNumberModel(ColourAdj.RGB_GAMMA_MIN, 
																						  ColourAdj.RGB_GAMMA_MIN, 
																						  ColourAdj.RGB_GAMMA_MAX, 
			  																			  1));
	private final JSpinner spinnerContrast   = new JSpinner(new SpinnerNumberModel(0, 
																				   ColourAdj.ADJUST_MIN, 
																				   ColourAdj.ADJUST_MAX, 
																				   1));
	private final JSpinner spinnerTint       = new JSpinner(new SpinnerNumberModel(0, 
																				   ColourAdj.ADJUST_MIN, 
																				   ColourAdj.ADJUST_MAX, 
																				   1));
	private final JSpinner spinnerColour     = new JSpinner(new SpinnerNumberModel(0, 
																				   ColourAdj.ADJUST_MIN, 
																				   ColourAdj.ADJUST_MAX, 
																				   1));
	private final JSpinner spinnerBrightness = new JSpinner(new SpinnerNumberModel(0, 
																				   ColourAdj.ADJUST_MIN, 
																				   ColourAdj.ADJUST_MAX, 
																				   1));
	private final JCheckBox checkNegative = new JCheckBox("Negative");
	private final JLabel labelRed = new JLabel("R");
	private final JLabel labelGreen = new JLabel("G");
	private final JLabel labelBlue = new JLabel("B");
	private final JLabel labelTint = new JLabel("Tint");
	private final JLabel labelColour = new JLabel("Colour");
	private final JLabel labelBright = new JLabel("Bright");
	private final JSpinner spinnerColourAreaNo = new JSpinner(new SpinnerNumberModel(new Byte("1"), 
																					 new Byte("1"),
																					 new Byte("5"), 
																					 new Byte("1")));
	private final JComboBox<ComboItem> comboColourAreaCorrection = new JComboBox<ComboItem>();
	private final JLabel labelNo = new JLabel("No.");
	private final JLabel labelLeft = new JLabel("L");
	private final JLabel labelWidth = new JLabel("W");
	private final JLabel labelBottom = new JLabel("B");
	private final JLabel labelHeight = new JLabel("H");

	private final JButton btnHolokotePreview = new JButton("HoloKote Preview");

	private final JTextArea textDriver2Msg = new JTextArea();
	private final JScrollPane scrollPane = new JScrollPane(textDriver2Msg);
	private final JButton btnClear = new JButton("Clear");

	private HANDLE hSession;
	private SDKlib SDK;

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

	public Driver2() {
		panelDriver2.setLayout(new MigLayout("", "[213.00][grow]", "[][][grow][][][grow][][93.00][]"));

		// ===== Action 'Panel' =====
		panelDriver2.add(panelAction, "cell 0 0 2 1,alignx center");
		panelAction.setLayout(new MigLayout("insets 0", "[][][]", "[]"));
		panelAction.add(labelAction, "flowx,cell 0 0 3 0,alignx left");
		panelAction.add(rdbtnGet, "cell 0 0");
		rdbtnGet.setSelected(true);
		buttonGroup.add(rdbtnGet);
		rdbtnGet.setActionCommand(RADIOGET);
		rdbtnGet.addActionListener(ah);
		buttonGroup.add(rdbtnSet);
		panelAction.add(rdbtnSet, "cell 0 0");
		buttonGroup.add(rdbtnSet);
		rdbtnSet.setActionCommand(RADIOSET);
		rdbtnSet.addActionListener(ah);

		// ===== Print Settings =====
		panelDriver2.add(panelPrintSettings, "cell 0 1");
		panelPrintSettings.setLayout(new MigLayout("", "[][132.00]", "[][][][]"));
		panelPrintSettings.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
													  "",
													  TitledBorder.LEADING, 
													  TitledBorder.TOP, 
													  null, 
													  new Color(0, 0, 0)));
		panelPrintSettings.add(labelPrintSides, "cell 0 0");
		comboDuplex.setEnabled(false);
		panelPrintSettings.add(comboDuplex, "cell 1 0,growx");
		comboDuplex.addItem(new ComboItem("Front Only", Duplex.FRONT_ONLY));
		comboDuplex.addItem(new ComboItem("Both Sides", Duplex.BOTH_SIDES));
		comboDuplex.addItem(new ComboItem("Back Only",  Duplex.BACK_ONLY));

		panelPrintSettings.add(labelCardSize, "cell 0 1,alignx left");
		comboCardSize.setEnabled(false);
		panelPrintSettings.add(comboCardSize, "cell 1 1,growx");

		panelPrintSettings.add(labelPrintCopies, "cell 0 2");
		spinnerCopies.setEnabled(false);
		panelPrintSettings.add(spinnerCopies, "flowx,cell 1 2,alignx left");

		panelPrintSettings.add(btnPrintSettings, "cell 0 3 2 1,alignx center");
		btnPrintSettings.setActionCommand(PRINT);
		btnPrintSettings.addActionListener(ah);

		// ===== Card Settings =====
		panelDriver2.add(panelCardSettings, "cell 0 2 1 2,growy");
		panelCardSettings.setLayout(new MigLayout("", "[][132.00]", "[][][][][]"));
		panelCardSettings.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
																		 "",
																		 TitledBorder.LEADING,
																		 TitledBorder.TOP,
																		 null,
																		 new Color(0, 0, 0)));

		panelCardSettings.add(labelCardSide, "flowx,cell 0 0,alignx left");
		panelCardSettings.add(comboCardSide, "cell 1 0,growx");
		comboCardSide.addItem(new ComboItem("FRONT", Side.FRONT));
		comboCardSide.addItem(new ComboItem("BACK",  Side.BACK));

		panelCardSettings.add(labelColourFormat, "flowx,cell 0 1,alignx left");
		comboColourFormat.setEnabled(false);
		panelCardSettings.add(comboColourFormat, "cell 1 1,growx");
		comboColourFormat.addItem(new ComboItem("YMC", ColourFormat.YMC));
		comboColourFormat.addItem(new ComboItem("YMCK", ColourFormat.YMCK));
		comboColourFormat.addItem(new ComboItem("K-Resin", ColourFormat.K));

		panelCardSettings.add(labelOrientation, "cell 0 2,alignx left");
		comboOrientation.setEnabled(false);
		panelCardSettings.add(comboOrientation, "cell 1 2,growx");
		comboOrientation.addItem(new ComboItem("Portrait", Orientation.PORTRAIT));
		comboOrientation.addItem(new ComboItem("Landscape", Orientation.LANDSCAPE));
		checkOvercoat.setEnabled(false);

		panelCardSettings.add(checkOvercoat, "cell 0 3");
		checkRotate.setEnabled(false);
		panelCardSettings.add(checkRotate, "cell 1 3,alignx right");

		panelCardSettings.add(btnCardSettings, "cell 0 4 2 1,alignx center");
		btnCardSettings.setActionCommand(CARD);
		btnCardSettings.addActionListener(ah);

		// ===== HoloKote =====
		panelDriver2.add(panelHoloKote, "cell 0 4 1 2,growy");
		panelHoloKote.setLayout(new MigLayout("", "[][132.00]", "[][][][][]"));
		panelHoloKote.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
																	 "",
																	 TitledBorder.LEADING,
																	 TitledBorder.TOP,
																	 null,
																	 new Color(0, 0, 0)));
		panelHoloKote.add(labelHoloKoteSide, "cell 0 0,alignx left");
		panelHoloKote.add(comboHoloKoteSide, "flowx,cell 1 0,growx");
		comboHoloKoteSide.addItem(new ComboItem("FRONT", Side.FRONT));
		comboHoloKoteSide.addItem(new ComboItem("BACK",  Side.BACK));

		panelHoloKote.add(labelHoloKoteMap, "cell 0 1");
		spinnerHoloKoteMap.setEnabled(false);
		panelHoloKote.add(spinnerHoloKoteMap, "cell 1 1,growx");
		JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) spinnerHoloKoteMap.getEditor();
		JFormattedTextField tf = editor.getTextField();
		tf.setFormatterFactory(new HexFormatterFactory());

		panelHoloKote.add(labelHoloKoteRotation, "cell 0 2,alignx left");
		comboHoloKoteRotation.setEnabled(false);
		panelHoloKote.add(comboHoloKoteRotation, "cell 1 2,growx");
		comboHoloKoteRotation.addItem(new ComboItem("None",        Rotation.NONE));
		comboHoloKoteRotation.addItem(new ComboItem("90 Degrees",  Rotation.DEGREES_90));
		comboHoloKoteRotation.addItem(new ComboItem("180 Degrees", Rotation.DEGREES_180));
		comboHoloKoteRotation.addItem(new ComboItem("270 Degrees", Rotation.DEGREES_270));

		panelHoloKote.add(checkUseLaminate, "flowx,cell 0 3 2 1");
		checkUseLaminate.setEnabled(false);

		panelHoloKote.add(checkNoCustomKey, "cell 0 3 2 1,alignx right");
		checkNoCustomKey.setEnabled(false);
		
		panelHoloKote.add(btnHoloKote, "flowx,cell 0 4 2 1,alignx left");
		btnHoloKote.setActionCommand(HOLOKOTE);
		btnHoloKote.addActionListener(ah);
		panelHoloKote.add(btnHolokotePreview, "cell 0 4");
		btnHolokotePreview.setActionCommand(HKPREVIEW);
		btnHolokotePreview.addActionListener(ah);

		panelHoloKote.add(labelID, "cell 1 0,alignx right");
		spinnerHoloKoteNo.setEnabled(false);
		panelHoloKote.add(spinnerHoloKoteNo, "cell 1 0,growx");

		// =====HoloPatch =====
		panelDriver2.add(panelHoloPatch, "cell 0 6,growy");
		panelHoloPatch.setLayout(new MigLayout("", "[][132.00]", "[][]"));
		panelHoloPatch.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
																	  "", 
																	  TitledBorder.LEADING,
																	  TitledBorder.TOP,
																	  null,
																	  new Color(0, 0, 0)));
		panelHoloPatch.add(labelPosition, "cell 0 0");
		panelHoloPatch.add(spinnerHoloPatch, "cell 1 0,growx");
		spinnerHoloPatch.setEnabled(false);

		panelHoloPatch.add(checkColourHole, "cell 0 1");
		checkColourHole.setEnabled(false);

		panelHoloPatch.add(btnHoloPatch, "cell 1 1,alignx center");
		btnHoloPatch.setActionCommand(HOLOPATCH);
		btnHoloPatch.addActionListener(ah);

		// ===== Colour Area =====
		panelDriver2.add(panelColourArea, "cell 0 7 1 2,growy");
		panelColourArea.setLayout(new MigLayout("", "[101.00][132.00]", "[][][][][]"));
		panelColourArea.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
																	   "",
																	   TitledBorder.LEADING,
																	   TitledBorder.TOP,
																	   null,
																	   new Color(0, 0, 0)));
		panelColourArea.add(labelSide, "flowx,cell 0 0,alignx left");
		panelColourArea.add(comboColourAreaSide, "cell 0 0,growx");
		comboColourAreaSide.addItem(new ComboItem("FRONT", Side.FRONT));
		comboColourAreaSide.addItem(new ComboItem("BACK",  Side.BACK));
		comboColourAreaSide.setActionCommand(CACHANGED);
		comboColourAreaSide.addActionListener(ah);

		panelColourArea.add(labelNo, "flowx,cell 1 0,alignx right");
		spinnerColourAreaNo.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				ColourAreaChanged();
			}
		});
		panelColourArea.add(spinnerColourAreaNo, "cell 1 0,alignx right");

		labelLeft.setHorizontalAlignment(SwingConstants.CENTER);
		panelColourArea.add(labelLeft, "flowx,cell 0 2");
		spinnerColourAreaL.setEnabled(false);
		spinnerColourAreaL.setEditor(new JSpinner.NumberEditor(spinnerColourAreaL, "#"));
		panelColourArea.add(spinnerColourAreaL, "cell 0 2,growx");

		labelWidth.setHorizontalAlignment(SwingConstants.CENTER);
		panelColourArea.add(labelWidth, "flowx,cell 1 2");
		panelColourArea.add(spinnerColourAreaW, "cell 1 2,growx");
		spinnerColourAreaW.setEnabled(false);
		spinnerColourAreaW.setEditor(new JSpinner.NumberEditor(spinnerColourAreaW, "#"));

		labelBottom.setHorizontalAlignment(SwingConstants.CENTER);
		panelColourArea.add(labelBottom, "flowx,cell 0 3");
		panelColourArea.add(spinnerColourAreaB, "cell 0 3,growx");
		spinnerColourAreaB.setEnabled(false);
		spinnerColourAreaB.setEditor(new JSpinner.NumberEditor(spinnerColourAreaB, "#"));

		labelHeight.setHorizontalAlignment(SwingConstants.CENTER);
		panelColourArea.add(labelHeight, "flowx,cell 1 3");
		panelColourArea.add(spinnerColourAreaH, "cell 1 3,growx");
		spinnerColourAreaH.setEnabled(false);
		spinnerColourAreaH.setEditor(new JSpinner.NumberEditor(spinnerColourAreaH, "#"));

		panelColourArea.add(labelCorrection, "flowx,cell 0 1 2 1");
		panelColourArea.add(comboColourAreaCorrection, "cell 0 1 2 1,growx");
		Driver1.InitCorrectionCombo(comboColourAreaCorrection);
		comboColourAreaCorrection.setEnabled(false);

		panelColourArea.add(btnColourArea, "cell 0 4 2 1,alignx center");
		btnColourArea.setActionCommand(COLOURAREA);
		btnColourArea.addActionListener(ah);

		// ===== Colour Adjust =====
		panelDriver2.add(panelColourAdjust, "cell 1 1 1 2,grow");
		panelColourAdjust.setLayout(new MigLayout("", "[::25%,grow][::25%,grow][::25%,grow][::25%,grow,fill]", "[1.00][][][7.00][][grow][][][][fill]"));
		panelColourAdjust.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
																		 "",
																		 TitledBorder.LEADING,
																		 TitledBorder.TOP,
																		 null,
																		 new Color(0, 0, 0)));
		panelColourAdjust.add(labelContrast, "flowx,cell 0 1 4 1,growx");
		labelContrast.setHorizontalAlignment(SwingConstants.CENTER);
		spinnerContrast.setEnabled(false);
		panelColourAdjust.add(spinnerContrast, "flowx,cell 0 2 4 1,growx");

		panelColourAdjust.add(labelBright, "cell 0 1 4 1,growx");
		labelBright.setHorizontalAlignment(SwingConstants.CENTER);
		spinnerBrightness.setEnabled(false);
		panelColourAdjust.add(spinnerBrightness, "cell 0 2 4 1,growx");

		panelColourAdjust.add(labelColour, "cell 0 1 4 1,growx");
		labelColour.setHorizontalAlignment(SwingConstants.CENTER);
		spinnerColour.setEnabled(false);
		panelColourAdjust.add(spinnerColour, "cell 0 2 4 1,growx");

		panelColourAdjust.add(labelTint, "cell 0 1 4 1,growx");
		labelTint.setHorizontalAlignment(SwingConstants.CENTER);
		spinnerTint.setEnabled(false);
		panelColourAdjust.add(spinnerTint, "cell 0 2 4 1,growx");

		panelColourAdjust.add(labelRed, "flowx,cell 0 3 4 1,growx");
		labelRed.setHorizontalAlignment(SwingConstants.CENTER);
		spinnerColourAdjustRed.setEnabled(false);
		panelColourAdjust.add(spinnerColourAdjustRed, "flowx,cell 0 4 4 1,growx");

		panelColourAdjust.add(labelGreen, "cell 0 3 4 1,growx");
		labelGreen.setHorizontalAlignment(SwingConstants.CENTER);
		spinnerColourAdjustGreen.setEnabled(false);
		panelColourAdjust.add(spinnerColourAdjustGreen, "cell 0 4 4 1,growx");

		panelColourAdjust.add(labelBlue, "cell 0 3 4 1,growx");
		labelBlue.setHorizontalAlignment(SwingConstants.CENTER);
		spinnerColourAdjustBlue.setEnabled(false);
		panelColourAdjust.add(spinnerColourAdjustBlue, "cell 0 4 4 1,growx");

		panelColourAdjust.add(labelIlluminant, "flowx,cell 0 6 4 1,alignx left");
		panelColourAdjust.add(comboIlluminant, "cell 0 6 4 1,growx");
		comboIlluminant.setEnabled(false);
		comboIlluminant.addItem(new ComboItem("Device Default", Illuminant.DEFAULT));
		comboIlluminant.addItem(new ComboItem("Tungsten Lamp", Illuminant.A));
		comboIlluminant.addItem(new ComboItem("Noon Sunlight", Illuminant.B));
		comboIlluminant.addItem(new ComboItem("NTSC Sunlight", Illuminant.C));
		comboIlluminant.addItem(new ComboItem("Normal Print", Illuminant.D50));
		comboIlluminant.addItem(new ComboItem("Bond Paper Print", Illuminant.D55));
		comboIlluminant.addItem(new ComboItem("Standard Daylight", Illuminant.D65));
		comboIlluminant.addItem(new ComboItem("Northern Daylight", Illuminant.D75));
		comboIlluminant.addItem(new ComboItem("Cool White Lamp", Illuminant.F2));

		panelColourAdjust.add(checkDarkPicture, "cell 0 5 2 1");
		checkDarkPicture.setEnabled(false);

		panelColourAdjust.add(checkNegative, "cell 2 5 2 1,alignx right");
		checkNegative.setEnabled(false);

		panelColourAdjust.add(labelBlackRef, "cell 0 7 2 1,alignx center");
		labelBlackRef.setHorizontalAlignment(SwingConstants.CENTER);

		panelColourAdjust.add(labelWhiteRef, "cell 2 7 2 1,alignx center");
		labelWhiteRef.setHorizontalAlignment(SwingConstants.CENTER);
		spinnerBlackRef.setEnabled(false);
		panelColourAdjust.add(spinnerBlackRef, "flowx,cell 0 8 2 1,alignx center");
		spinnerWhiteRef.setEnabled(false);
		panelColourAdjust.add(spinnerWhiteRef, "cell 2 8 2 1,alignx center");

		panelColourAdjust.add(btnColourAdjust, "cell 0 9 4 1,alignx center");
		btnColourAdjust.setActionCommand(COLOURADJUST);
		btnColourAdjust.addActionListener(ah);

		// ===== Text Area =====
		panelDriver2.add(scrollPane, "cell 1 3 1 5,grow");
		textDriver2Msg.setBorder(BorderFactory.createLineBorder(Color.black));

		// ===== Clear Button =====
		panelDriver2.add(btnClear, "cell 1 8,alignx center");
		btnClear.setActionCommand(CLEAR);
		btnClear.addActionListener(ah);
	}

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

	class MediaCombo {
		private Media key;
		private int value;

		public MediaCombo(Media res, int value) {
			this.key   = res;
			this.value = value;
		}

		public String toString() {return key.toString();}
		public int    getValue() {return value;}
	}

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

	@SuppressWarnings("serial")
	private static class HexFormatterFactory extends DefaultFormatterFactory {
		public AbstractFormatter getDefaultFormatter() {
			return new HexFormatter();
		}
	}

	@SuppressWarnings("serial")
	private static class HexFormatter extends DefaultFormatter {
		public Object stringToValue(String text) throws ParseException {
			try {
				return Integer.valueOf(text, 16);
			} catch (NumberFormatException nfe) {
				throw new ParseException(text, 0);
			}
		}

		public String valueToString(Object value) {
			Integer temp = ((Number) value).intValue();
			String tempstr = Integer.toHexString(temp).toUpperCase();
			return tempstr;
		}
	}

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

	private void InitCardSizeCombo(String printername) {
		AttributeSet aset = new HashAttributeSet();
		aset.add(new PrinterName(printername, null));

		PrintService[] services = PrintServiceLookup.lookupPrintServices(null, aset);
		for (int i = 0; i < services.length; i++) {
			PrintService service = (PrintService)services[i];

			Object o = service.getSupportedAttributeValues(Media.class, null, null);
			if (o != null && o.getClass().isArray()) {
				for (Media res: (Media[])o) {
					if (res instanceof MediaSizeName) {
						//For >JDK8, paper ID cannot be found using Win32PrintService
						//CR80 has a paper ID of 261, and CR79 is 260
						MediaSize mediaSize = MediaSize.getMediaSizeForName((MediaSizeName) res);
						float xSizemm = mediaSize.getX(MediaSize.MM);
						if (Float.compare(xSizemm, (float) 54.4) == 0) {
							comboCardSize.addItem(new MediaCombo(res, 261));
						} 
						else if (Float.compare(xSizemm, (float) 52.1) == 0) {
							comboCardSize.addItem(new MediaCombo(res, 260));
						}
					
					}
				}
			}
		}
	}

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

	void Init(HANDLE handle, SDKlib sdk, String printername) {
		tabbedPane.addTab("Driver 2", null, panelDriver2, null);
		this.hSession = handle;
		this.SDK      = sdk;

		spinnerColourAreaL.setModel(new SpinnerNumberModel(0, 0, maxXCoord, 1));
		spinnerColourAreaW.setModel(new SpinnerNumberModel(0, 0, maxCardLength, 1));

		InitCardSizeCombo(printername);

		GetPrintSettings(new PrintSettings());
		GetCardSettings(Side.FRONT, new CardSettings());
		GetHoloKote(Side.FRONT, new HoloKote());
		GetHoloPatch(new HoloPatch());
		GetColourArea(Side.FRONT, (byte)1, new Area(), new ByteByReference());
		GetColourAdjust(new ColourAdj());
	}

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

	private void GetSetControls(Boolean state) {
		comboDuplex.setEnabled(state);
		comboCardSize.setEnabled(state);
		spinnerCopies.setEnabled(state);
		comboColourFormat.setEnabled(state);
		comboOrientation.setEnabled(state);
		checkOvercoat.setEnabled(state);
		checkRotate.setEnabled(state);
		spinnerHoloKoteNo.setEnabled(state);
		spinnerHoloKoteMap.setEnabled(state);
		checkUseLaminate.setEnabled(state);
		checkNoCustomKey.setEnabled(state);
		comboHoloKoteRotation.setEnabled(state);
		spinnerHoloPatch.setEnabled(state);
		checkColourHole.setEnabled(state);
		spinnerColourAreaL.setEnabled(state);
		spinnerColourAreaW.setEnabled(state);
		spinnerColourAreaB.setEnabled(state);
		spinnerColourAreaH.setEnabled(state);
		comboColourAreaCorrection.setEnabled(state);

		spinnerContrast.setEnabled(state);
		spinnerBrightness.setEnabled(state);
		spinnerColour.setEnabled(state);
		spinnerTint.setEnabled(state);
		spinnerColourAdjustRed.setEnabled(state);
		spinnerColourAdjustGreen.setEnabled(state);
		spinnerColourAdjustBlue.setEnabled(state);
		comboIlluminant.setEnabled(state);
		checkDarkPicture.setEnabled(state);
		checkNegative.setEnabled(state);
		spinnerBlackRef.setEnabled(state);
		spinnerWhiteRef.setEnabled(state);
	}

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

	private void ClearMsg() {
		textDriver2Msg.setText(null);
	}

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

	private String DuplexString(byte duplex) {
		return ((ComboItem)comboDuplex.getSelectedItem()).toString();
	}

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

	private String CardSizeString(int cardSize) {
		return ((MediaCombo)comboCardSize.getSelectedItem()).toString();
	}

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

	private void PrintSettingsToMsgBox(byte action, PrintSettings PS) {
		String sep = Separator(action);
		textDriver2Msg.append("Duplex"       + sep + DuplexString(PS.duplex)     + "\n"
				  			  + "Card Size"  + sep + CardSizeString(PS.cardSize) + "\n"
				  			  + "Copy Count" + sep + PS.copyCount                + "\n\n");
	}

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

	private byte GetPrintSettings(PrintSettings PS) {
		byte sdkReturn = SDK.ID_PrintSettings(hSession, Action.READ, PS);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetPrintSettings", sdkReturn);
		} 
		else {
			comboDuplex.setSelectedIndex(PS.duplex);
			spinnerCopies.setValue(PS.copyCount);
			comboCardSize.setSelectedItem(PS.cardSize);
		}
		return sdkReturn;
	}

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

	private void PrintSettings() {
		PrintSettings PS = new PrintSettings();
		if (rdbtnGet.isSelected()) {
			if (GetPrintSettings(PS) == Return.SUCCESS) {
				PrintSettingsToMsgBox(Action.READ, PS);
			}
		} 
		else {
			PS.duplex    = ((ComboItem)comboDuplex.getSelectedItem()).getValue();
			PS.copyCount = (byte)spinnerCopies.getValue();
			PS.cardSize  = ((MediaCombo)comboCardSize.getSelectedItem()).getValue();

			byte sdkReturn = SDK.ID_PrintSettings(hSession, Action.WRITE, PS);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("SetPrintSettings", sdkReturn);
			} 
			else {
				PrintSettingsToMsgBox(Action.WRITE, PS);
			}
		}
	}

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

	private String ColourFormatString(byte format) {
		return ((ComboItem)comboColourFormat.getSelectedItem()).toString();
	}

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

	private String OrientationString(byte orientation) {
		return ((ComboItem)comboOrientation.getSelectedItem()).toString();
	}

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

	private void CardSettingsChanged() {
		CardSettings CS = new CardSettings();
		if (GetCardSettings(((ComboItem)comboCardSide.getSelectedItem()).getValue(), CS) == Return.SUCCESS) {
			SetCardSettings(CS);
		}
	}

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

	private void SetCardSettings(CardSettings CS) {
		comboColourFormat.setSelectedIndex(CS.colourFormat);
		checkOvercoat.setSelected(CS.overcoat);
		comboOrientation.setSelectedIndex(CS.orientation);
		checkRotate.setSelected(CS.rotation);
	}

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

	private void CardSettingsToMsgBox(byte action, CardSettings CS) {
		String sep = Separator(action);
		textDriver2Msg.append("CardSettings (" 
				  			  + ((ComboItem)comboCardSide.getSelectedItem()).toString()	+ ")" + "\n"
				  			  + "Colour Format" + sep + ColourFormatString(CS.colourFormat)   + "\n"
				  			  + "Overcoat"      + sep + OnOffString(CS.overcoat)              + "\n"
				  			  + "Orientation"   + sep + OrientationString(CS.orientation)     + "\n"
				  			  + "Rotation"      + sep + OnOffString(CS.rotation)              + "\n\n");
	}

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

	private byte GetCardSettings(byte side, CardSettings CS) {
		byte sdkReturn = SDK.ID_CardSettings(hSession, Action.READ, side, CS);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetCardSettings", sdkReturn);
		} 
		else {
			SetCardSettings(CS);
		}
		return sdkReturn;
	}

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

	private void CardSettings() {
		CardSettings CS = new CardSettings();
		byte side = ((ComboItem)comboCardSide.getSelectedItem()).getValue();
		if (rdbtnGet.isSelected()) {
			if (GetCardSettings(side, CS) == Return.SUCCESS) {
				CardSettingsToMsgBox(Action.READ, CS);
			}
		}
		else {
			CS.colourFormat = ((ComboItem)comboColourFormat.getSelectedItem()).getValue();
			CS.overcoat     = checkOvercoat.isSelected();
			CS.orientation  = ((ComboItem)comboOrientation.getSelectedItem()).getValue();
			CS.rotation     = checkRotate.isSelected();

			byte sdkReturn = SDK.ID_CardSettings(hSession, Action.WRITE, side, CS);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("SetCardSettings", sdkReturn);
			} 
			else {
				CardSettingsToMsgBox(Action.WRITE, CS);
			}
		}
	}

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

	private String RotationString(byte rotation) {
		return ((ComboItem)comboHoloKoteRotation.getSelectedItem()).toString();
	}

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

	private void HoloKoteChanged() {
		HoloKote HK = new HoloKote();

		if (GetHoloKote(((ComboItem)comboHoloKoteSide.getSelectedItem()).getValue(), HK) == Return.SUCCESS) {
			SetHoloKote(HK);
		}
	}

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

	private void SetHoloKote(HoloKote HK) {
		spinnerHoloKoteNo.setValue(HK.imageID);
		spinnerHoloKoteMap.setValue(HK.map);
		comboHoloKoteRotation.setSelectedIndex(HK.rotation);
		checkNoCustomKey.setSelected(HK.disableCustomKey);
		checkUseLaminate.setSelected(HK.useLaminate);
	}

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

	private void HoloKoteToMsgBox(byte action, HoloKote HK) {
		String sep = Separator(action);
		textDriver2Msg.append("HoloKote (" + ((ComboItem)comboHoloKoteSide.getSelectedItem()).toString() + ")");
		if (HK.imageID == 0) {
			textDriver2Msg.append(sep + "Disabled\n\n");
		} 
		else {
			textDriver2Msg.append("\n"
								  + "ImageID"          + sep + HK.imageID + "\n"
								  + "HoloKoteMap"      + sep + Integer.toHexString(HK.map).toUpperCase() + "\n"
								  + "Rotation"         + sep + RotationString(HK.rotation) + "\n"
								  + "UseLaminate"      + sep + OnOffString(HK.useLaminate) + "\n"
								  + "DisableCustomKey" + sep + OnOffString(HK.disableCustomKey) + "\n\n");
		}
	}

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

	private byte GetHoloKote(byte side, HoloKote HK) {
		byte sdkReturn = SDK.ID_HoloKote(hSession, Action.READ, side, HK);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetHoloKote", sdkReturn);
		} 
		else {
			SetHoloKote(HK);
		}
		return sdkReturn;
	}

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

	private void HoloKote() {
		HoloKote HK = new HoloKote();
		byte side = ((ComboItem)comboHoloKoteSide.getSelectedItem()).getValue();
		if (rdbtnGet.isSelected()) {
			if (GetHoloKote(side, HK) == Return.SUCCESS) {
				HoloKoteToMsgBox(Action.READ, HK);
			}
		} 
		else {
			HK.imageID          = (byte)spinnerHoloKoteNo.getValue();
			HK.map              = (int)spinnerHoloKoteMap.getValue();
			HK.rotation         = ((ComboItem)comboHoloKoteRotation.getSelectedItem()).getValue();
			HK.disableCustomKey = checkNoCustomKey.isSelected();
			HK.useLaminate      = checkUseLaminate.isSelected();

			byte sdkReturn = SDK.ID_HoloKote(hSession, Action.WRITE, side, HK);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("SetHoloKote", sdkReturn);
			} 
			else {
				HoloKoteToMsgBox(Action.WRITE, HK);
			}
		}
	}

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

	private void HoloPatchToMsgBox(byte action, HoloPatch HP) {
		String sep = Separator(action);
		if (HP.position == 0) {
			textDriver2Msg.append("HoloPatch" + sep + "Disabled\n\n");
		} 
		else {
			textDriver2Msg.append("HoloPatch\n" 
								  + "Position"   + sep + HP.position + "\n"
								  + "ColourHole" + sep + OnOffString(HP.colourHole) + "\n\n");
		}
	}

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

	private byte GetHoloPatch(HoloPatch HP) {
		byte sdkReturn = SDK.ID_HoloPatch(hSession, Action.READ, HP);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetHoloPatch", sdkReturn);
		} 
		else {
			spinnerHoloPatch.setValue(HP.position);
			checkColourHole.setSelected(HP.colourHole);
		}
		return sdkReturn;
	}

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

	private void HoloPatch() {
		HoloPatch HP = new HoloPatch();
		if (rdbtnGet.isSelected()) {
			if (GetHoloPatch(HP) == Return.SUCCESS) {
				HoloPatchToMsgBox(Action.READ, HP);
			}
		} 
		else {
			byte temp = (byte) spinnerHoloPatch.getValue();
			HP.position = temp;
			HP.colourHole = checkColourHole.isSelected();

			byte sdkReturn = SDK.ID_HoloPatch(hSession, Action.WRITE, HP);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("SetHoloPatch", sdkReturn);
			} 
			else {
				HoloPatchToMsgBox(Action.WRITE, HP);
			}
			textDriver2Msg.append("\n");
		}
	}

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

	private void ColourAreaChanged() {
		Area RA = new Area();

		// Colour Area settings have been changed
		byte side    = ((ComboItem)comboColourAreaSide.getSelectedItem()).getValue();
		byte areaNo = (byte)spinnerColourAreaNo.getValue();
		ByteByReference correction = new ByteByReference(
				((ComboItem)comboColourAreaCorrection.getSelectedItem()).getValue());

		if (GetColourArea(side, areaNo, RA, correction) == Return.SUCCESS) {
			SetColourArea(RA, correction.getValue());
		}
	}

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

	private String CorrectionString(byte correction) {
		return ((ComboItem)comboColourAreaCorrection.getSelectedItem()).toString();
	}

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

	private void ColourAreaToMsgBox(byte side, byte areaNo, Area RA, byte action, byte correction) {
		String sep = Separator(action);
		textDriver2Msg.append("Colour Area " 
							  + ((ComboItem)comboColourAreaSide.getSelectedItem()).toString()
							  + " " + areaNo + "\n" 
							  + "Left"   + sep + RA.left   + "\n"
							  + "Width"  + sep + RA.width  + "\n"
							  + "Bottom" + sep + RA.bottom + "\n"
							  + "Height" + sep + RA.height + "\n"
							  + "Correction" + sep + CorrectionString(correction) + "\n\n");
	}

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

	private void SetColourArea(Area RA, byte correction) {
		spinnerColourAreaL.setValue(RA.left);
		spinnerColourAreaW.setValue(RA.width);
		spinnerColourAreaB.setValue(RA.bottom);
		spinnerColourAreaH.setValue(RA.height);
		comboColourAreaCorrection.setSelectedIndex(correction);
	}

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

	private byte GetColourArea(byte side, byte areaNo, Area area, ByteByReference correction) {
		byte sdkReturn = SDK.ID_ColourArea(hSession, Action.READ, side, areaNo, area, correction);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetColourArea", sdkReturn);
		} 
		else {
			SetColourArea(area, correction.getValue());
		}

		return sdkReturn;
	}

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

	private void ColourArea() {
		Area RA = new Area();
		byte side   = ((ComboItem)comboColourAreaSide.getSelectedItem()).getValue();
		byte areaNo = (byte)spinnerColourAreaNo.getValue();
		ByteByReference correction = new ByteByReference(
				((ComboItem)comboColourAreaCorrection.getSelectedItem()).getValue());

		if (rdbtnGet.isSelected()) {
			if (GetColourArea(side, areaNo, RA, correction) == Return.SUCCESS) {
				ColourAreaToMsgBox(side, areaNo, RA, Action.READ, correction.getValue());
			}
		}
		else {
			RA.left   = (int)spinnerColourAreaL.getValue();
			RA.width  = (int)spinnerColourAreaW.getValue();
			RA.bottom = (int)spinnerColourAreaB.getValue();
			RA.height = (int)spinnerColourAreaH.getValue();

			byte sdkReturn = SDK.ID_ColourArea(hSession, Action.WRITE, side, areaNo, RA, correction);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("SetColourArea", sdkReturn);
			}
			else {
				ColourAreaToMsgBox(side, areaNo, RA, Action.WRITE, correction.getValue());
			}
		}
	}

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

	private String IlluminantString(byte index) {
		return ((ComboItem)comboIlluminant.getSelectedItem()).toString();
	}

	// ****************************************************************************

	private void ColourAdjToMsgBox(ColourAdj ca, byte action) {
		String sep = Separator(action);
		textDriver2Msg.append("Contrast"          + sep + ca.contrast   + "\n"
							  + "Brightness"      + sep + ca.brightness + "\n"
							  + "Colorfulness"    + sep + ca.colour     + "\n"
							  + "RedGreenTint"    + sep + ca.tint       + "\n"
							  + "RedGamma"        + sep + ca.red        + "\n"
							  + "GreenGamma"      + sep + ca.green      + "\n"
							  + "BlueGamma"       + sep + ca.blue       + "\n"
							  + "IlluminantIndex" + sep + IlluminantString((byte)ca.illuminant) + "\n"
							  + "Dark Picture"    + sep + OnOffString((ca.flags & Flags.LOG_FILTER) != 0) + "\n"
							  + "Negative"        + sep + OnOffString((ca.flags & Flags.NEGATIVE) != 0) + "\n"
							  + "ReferenceBlack"  + sep + ca.refBlack   + "\n"
							  + "ReferenceWhite"  + sep + ca.refWhite   + "\n\n");
	}

	// ****************************************************************************

	private void SetColourAdjust(ColourAdj ca) {
		spinnerContrast.setValue(ca.contrast);
		spinnerBrightness.setValue(ca.brightness);
		spinnerColour.setValue(ca.colour);
		spinnerTint.setValue(ca.tint);
		spinnerColourAdjustRed.setValue(ca.red);
		spinnerColourAdjustGreen.setValue(ca.green);
		spinnerColourAdjustBlue.setValue(ca.blue);
		comboIlluminant.setSelectedItem(ca.illuminant);
		spinnerBlackRef.setValue(ca.refBlack);
		spinnerWhiteRef.setValue(ca.refWhite);
		checkNegative.setSelected((ca.flags & Flags.LOG_FILTER) != 0);
		checkDarkPicture.setSelected((ca.flags & Flags.NEGATIVE) != 0);
	}

	// ****************************************************************************

	private byte GetColourAdjust(ColourAdj pca) {
		byte sdkReturn = SDK.ID_ColourAdjust(hSession, Action.READ, pca);
		if (sdkReturn == Return.SUCCESS) {
			SetColourAdjust(pca);
		} 
		else {
			DisplayError("GetColourAdjust", sdkReturn);
		}

		return sdkReturn;
	}

	// ****************************************************************************

	private void ColourAdjust() {
		ColourAdj ColAdjust = new ColourAdj();

		if (rdbtnGet.isSelected()) {
			if (GetColourAdjust(ColAdjust) == Return.SUCCESS) {
				ColourAdjToMsgBox(ColAdjust, Action.READ);
			}
		}
		else {
			ColAdjust.contrast   = (int)spinnerContrast.getValue();
			ColAdjust.brightness = (int)spinnerBrightness.getValue();
			ColAdjust.colour     = (int)spinnerColour.getValue();
			ColAdjust.tint       = (int)spinnerTint.getValue();
			ColAdjust.red        = (int)spinnerColourAdjustRed.getValue();
			ColAdjust.green      = (int)spinnerColourAdjustGreen.getValue();
			ColAdjust.blue       = (int)spinnerColourAdjustBlue.getValue();
			ColAdjust.refBlack   = (int)spinnerBlackRef.getValue();
			ColAdjust.refWhite   = (int)spinnerWhiteRef.getValue();
			ColAdjust.illuminant = ((ComboItem)comboIlluminant.getSelectedItem()).getValue();
			ColAdjust.flags      = 0;
			if (checkNegative.isSelected())    ColAdjust.flags |= Flags.NEGATIVE;
			if (checkDarkPicture.isSelected()) ColAdjust.flags |= Flags.LOG_FILTER;

			byte sdkReturn = SDK.ID_ColourAdjust(hSession, Action.WRITE, ColAdjust);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("SetColourAdjust", sdkReturn);
			} 
			else {
				ColourAdjToMsgBox(ColAdjust, Action.WRITE);
			}
		}
	}

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

	private void PreviewHoloKotes() {
		CursorWait();

		int maxHoloKotes = SDK.ID_HoloKoteCount(hSession);
		BufferedImage[] previews = new BufferedImage[maxHoloKotes];
		
		byte sdkReturn = SDK.ID_HoloKotePreview(hSession, previews);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("HolokotePreview", sdkReturn);
		}
		else 
		{
			new HKPreview(new JFrame(), this.SDK, previews);
		}

		CursorDefault();
	}

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

	class ActionHandler implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			switch (e.getActionCommand()) {
			case RADIOGET:     GetSetControls(false); break;
			case RADIOSET:     GetSetControls(true);  break;
			case CLEAR:        ClearMsg();            break;
			case PRINT:        PrintSettings();       break;
			case CARD:         CardSettings();        break;
			case CSCHANGED:    CardSettingsChanged(); break;
			case HOLOKOTE:     HoloKote();            break;
			case HKCHANGED:    HoloKoteChanged();     break;
			case HOLOPATCH:    HoloPatch();           break;
			case COLOURAREA:   ColourArea();          break;
			case CACHANGED:    ColourAreaChanged();   break;
			case COLOURADJUST: ColourAdjust();        break;
			case HKPREVIEW:    PreviewHoloKotes();    break;
			}
		}
	}
}
