package DTCDemo;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
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.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import net.miginfocom.swing.MigLayout;
import SDK.SDKlib;
import SDK.SDKlib.Action;
import SDK.SDKlib.Area;
import SDK.SDKlib.AreaHole;
import SDK.SDKlib.Correction;
import SDK.SDKlib.GUIControl;
import SDK.SDKlib.Model;
import SDK.SDKlib.PowerLevel;
import SDK.SDKlib.PrintSpeed;
import SDK.SDKlib.PrinterType;
import SDK.SDKlib.Return;
import SDK.SDKlib.Rewritable;
import SDK.SDKlib.Side;

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

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

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

public class Driver1 {
	static final int MAX_POWER     = 99;
	static final int MAX_SHARPNESS = 2;
	static final int MIN_SHARPNESS = -2;

	private final String RADIOGET      = "RADIOGET";
	private final String RADIOSET      = "RADIOSET";
	private final String CLEAR         = "CLEAR";
	private final String GUICONTROL    = "GUICONTROL";
	private final String SHARPNESS     = "SHARPNESS";
	private final String COLOUR        = "COLOUR";
	private final String POWERLEVEL    = "POWERLEVEL";
	private final String PRINTSPEED    = "PRINTSPEED";
	private final String RESINAREA     = "RESINAREA";
	private final String RASIDE        = "RASIDE";
	private final String AREAHOLE      = "AREAHOLE";
	private final String AHSIDE        = "AHSIDE";
	private final String AHTYPE        = "AHTYPE";
	private final String REWRITABLE    = "REWRITABLE";
	private final String PRINTABLEAREA = "PRINTABLEAREA";
	private final String RESOLUTION    = "RESOLUTION";
	
	private final ActionHandler ah = new ActionHandler();

	public static final JPanel panelDriver1 = new JPanel();
	public static final String DRIVER1_TAB_TITLE = "Driver 1";
	
	private final JPanel panelGeneral = 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 JCheckBox checkUser = new JCheckBox("User");
	private final JCheckBox checkPrinter = new JCheckBox("Printer");
	private final JButton btnGUIControl = new JButton("GUI Control");
	private final JSpinner spinnerSharpness = new JSpinner(new SpinnerNumberModel(0, MIN_SHARPNESS, MAX_SHARPNESS, 1));
	private final JButton btnSharpness = new JButton("Sharpness");
	private final JComboBox<ComboItem> comboCorrection = new JComboBox<ComboItem>();
	private final JButton btnColour = new JButton("Colour Corr.");
	private final JComboBox<ComboItem> comboPrintSpeed = new JComboBox<ComboItem>();
	private final JButton btnPrintSpeed = new JButton("Print Speed");

	private final JPanel panelPowerLevel = new JPanel();
	private final JLabel labelYMC      = new JLabel("YMC");
	private final JLabel labelResin    = new JLabel("Resin");
	private final JLabel labelOvercoat = new JLabel("Overcoat");
	private final JSpinner spinnerYMCPower      = new JSpinner(new SpinnerNumberModel(0, 0, MAX_POWER, 1));
	private final JSpinner spinnerResinPower    = new JSpinner(new SpinnerNumberModel(0, 0, MAX_POWER, 1));
	private final JSpinner spinnerOvercoatPower = new JSpinner(new SpinnerNumberModel(0, 0, MAX_POWER, 1));
	private final JButton btnPowerLevel = new JButton("Power Level");

	private final JPanel panelResinArea = new JPanel();
	private final JLabel labelResinSide = new JLabel("Side");
	private final JComboBox<ComboItem> comboResinAreaSide = new JComboBox<ComboItem>();
	private final JLabel labelResinAreaNo = new JLabel("No.");
	private final JSpinner spinnerResinAreaNo = new JSpinner(new SpinnerNumberModel(new Byte("1"), 
																					new Byte("1"), 
																					new Byte("5"), 
																					new Byte("1")));
	private final JLabel labelResinL = new JLabel("L");
	private final JLabel labelResinW = new JLabel("W");
	private final JLabel labelResinB = new JLabel("B");
	private final JLabel labelResinH = new JLabel("H");
	private final JSpinner spinnerResinL = new JSpinner(new SpinnerNumberModel(0, 0, maxXCoord, 1));
	private final JSpinner spinnerResinW = new JSpinner(new SpinnerNumberModel(0, 0, maxCardLength, 1));
	private final JSpinner spinnerResinB = new JSpinner(new SpinnerNumberModel(0, 0, MAX_Y_COORD, 1));
	private final JSpinner spinnerResinH = new JSpinner(new SpinnerNumberModel(0, 0, MAX_CARD_HEIGHT, 1));
	private final JButton btnResinArea = new JButton("Resin Area");

	private final JPanel panelAreaHole = new JPanel();
	private final JLabel labelAreaHoleSide = new JLabel("Side");
	private final JComboBox<ComboItem> comboAreaHoleSide = new JComboBox<ComboItem>();
	private final JLabel labelAreaHoleNo = new JLabel("No.");
	private final JSpinner spinnerAreaHoleNo = new JSpinner(new SpinnerNumberModel(new Byte("1"), 
																				   new Byte("1"), 
																				   new Byte("2"), 
																				   new Byte("1")));
	private final JLabel labelAreaHoleType = new JLabel("Type");
	private final JComboBox<ComboItem> comboAreaHoleType = new JComboBox<ComboItem>();
	private final JLabel labelAreaHoleL = new JLabel("L");
	private final JLabel labelAreaHoleW = new JLabel("W");
	private final JLabel labelAreaHoleB = new JLabel("B");
	private final JLabel labelAreaHoleH = new JLabel("H");
	private final JSpinner spinnerAreaHoleL = new JSpinner(new SpinnerNumberModel(0, 0, maxXCoord, 1));
	private final JSpinner spinnerAreaHoleW = new JSpinner(new SpinnerNumberModel(0, 0, maxCardLength, 1));
	private final JSpinner spinnerAreaHoleB = new JSpinner(new SpinnerNumberModel(0, 0, MAX_Y_COORD,  1));
	private final JSpinner spinnerAreaHoleH = new JSpinner(new SpinnerNumberModel(0, 0, MAX_CARD_HEIGHT,  1));
	private final JButton btnAreaHole = new JButton("Area/Hole");

	private final JPanel panelRewritable = new JPanel();
	private final JLabel labelL = new JLabel("L");
	private final JLabel labelW = new JLabel("W");
	private final JLabel labelB = new JLabel("B");
	private final JLabel labelH = new JLabel("H");
	private final JSpinner spinnerEraseAreaL = new JSpinner(new SpinnerNumberModel(0, 0, maxXCoord, 1));
	private final JSpinner spinnerEraseAreaW = new JSpinner(new SpinnerNumberModel(0, 0, maxCardLength, 1));
	private final JSpinner spinnerEraseAreaB = new JSpinner(new SpinnerNumberModel(0, 0, MAX_Y_COORD,  1));
	private final JSpinner spinnerEraseAreaH = new JSpinner(new SpinnerNumberModel(0, 0, MAX_CARD_HEIGHT,  1));
	private final JLabel labelPower = new JLabel("Power");
	private final JLabel labelWritePower = new JLabel("Write");
	private final JSpinner spinnerEraseWrite = new JSpinner(new SpinnerNumberModel(0, 0, MAX_POWER, 1));
	private final JCheckBox checkEraseBeforePrint = new JCheckBox("Erase before Print");
	private final JLabel labelStartPower = new JLabel("Start");
	private final JSpinner spinnerEraseStart = new JSpinner(new SpinnerNumberModel(0, 0, MAX_POWER, 1));
	private final JLabel labelEndPower = new JLabel("End");
	private final JSpinner spinnerEraseEnd = new JSpinner(new SpinnerNumberModel(0, 0, MAX_POWER, 1));
	private final JButton btnRewritable = new JButton("Rewritable");

	private final JPanel panelPrintableArea = new JPanel();
	private final JLabel labelPrintableAreaL = new JLabel("L");
	private final JLabel labelPrintableAreaW = new JLabel("W");
	private final JLabel labelPrintableAreaB = new JLabel("B");
	private final JLabel labelPrintableAreaH = new JLabel("H");
	private final JSpinner spinnerPrintableAreaL = new JSpinner(new SpinnerNumberModel(0, 0, maxXCoord, 1));
	private final JSpinner spinnerPrintableAreaW = new JSpinner(new SpinnerNumberModel(0, 0, maxCardLength, 1));
	private final JSpinner spinnerPrintableAreaB = new JSpinner(new SpinnerNumberModel(0, 0, MAX_Y_COORD, 1));
	private final JSpinner spinnerPrintableAreaH = new JSpinner(new SpinnerNumberModel(0, 0, MAX_CARD_HEIGHT, 1));
	private final JButton btnPrintableArea = new JButton("Printable Area");

	private final JPanel panelResolution = new JPanel();
	private final JRadioButton rdbtn300DPI = new JRadioButton("300 x 300 DPI");
	private final ButtonGroup buttonGroupResolution = new ButtonGroup();
	
	private final JTextArea textDriver1Msg = new JTextArea();
	private final JScrollPane scrollPane = new JScrollPane(textDriver1Msg);    
	private final JButton btnClear = new JButton("Clear");

	private HANDLE hSession;
	private SDKlib SDK;

	//**********************
	
	public final JRadioButton rdbtn600DPI = new JRadioButton("600 x 300 DPI");
	public final JButton btnResolution = new JButton("Resolution");

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

	public Driver1() {
		panelDriver1.setLayout(new MigLayout("", "[pref!][203.00,grow]", "[][][grow][][][110.00][28.00]"));

		// ===== Action Radio Buttons =====
		panelDriver1.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");
		buttonGroup.add(rdbtnGet);
		rdbtnGet.setActionCommand(RADIOGET);
		rdbtnGet.addActionListener(ah);
		rdbtnGet.setSelected(true);
		panelAction.add(rdbtnSet, "cell 0 0");
		buttonGroup.add(rdbtnSet);
		rdbtnSet.setActionCommand(RADIOSET);
		rdbtnSet.addActionListener(ah);

		// ===== General Controls =====
		panelDriver1.add(panelGeneral, "cell 0 1,grow");
		panelGeneral.setLayout(new MigLayout("", "[100.00,grow][grow][grow]", "[][][][]"));
		panelGeneral.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
							                    "", 
							                    TitledBorder.LEADING, 
							                    TitledBorder.TOP, 
							                    null, 
							                    new Color(0, 0, 0)));

		panelGeneral.add(btnGUIControl, "cell 0 0,growx");
		checkUser.setEnabled(false);
		panelGeneral.add(checkUser, "cell 1 0,alignx right");
		checkPrinter.setEnabled(false);
		panelGeneral.add(checkPrinter, "cell 2 0,alignx right");
		btnGUIControl.setActionCommand(GUICONTROL);
		btnGUIControl.addActionListener(ah);

		panelGeneral.add(btnSharpness, "cell 0 1,growx");
		spinnerSharpness.setEnabled(false);
		panelGeneral.add(spinnerSharpness, "cell 1 1 2 1,growx");
		btnSharpness.setActionCommand(SHARPNESS);
		btnSharpness.addActionListener(ah);

		panelGeneral.add(btnColour, "cell 0 2,growx");
		comboCorrection.setEnabled(false);
		panelGeneral.add(comboCorrection, "cell 1 2 2 1,growx");
		InitCorrectionCombo(comboCorrection);
		btnColour.setActionCommand(COLOUR);
		btnColour.addActionListener(ah);

		panelGeneral.add(btnPrintSpeed, "cell 0 3,growx");
		comboPrintSpeed.setEnabled(false);
		panelGeneral.add(comboPrintSpeed, "cell 1 3 2 1,growx");
		comboPrintSpeed.addItem(new ComboItem("High",   PrintSpeed.HIGH));
		comboPrintSpeed.addItem(new ComboItem("Normal", PrintSpeed.NORMAL));
		btnPrintSpeed.setActionCommand(PRINTSPEED);
		btnPrintSpeed.addActionListener(ah);
		
		// ===== Power Level =====
		panelDriver1.add(panelPowerLevel, "cell 0 2,grow");
		panelPowerLevel.setLayout(new MigLayout("",
				"[grow 33,center][grow 33,center][grow 33,center]", "[][][]"));
		panelPowerLevel.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
								                   "", 
								                   TitledBorder.LEADING,	
								                   TitledBorder.TOP, 
								                   null, 
								                   new Color(0, 0, 0)));
		panelPowerLevel.add(labelYMC, "cell 0 0");
		panelPowerLevel.add(labelResin, "cell 1 0");
		panelPowerLevel.add(labelOvercoat, "cell 2 0");
		spinnerYMCPower.setEnabled(false);
		panelPowerLevel.add(spinnerYMCPower, "cell 0 1,growx");
		spinnerResinPower.setEnabled(false);
		panelPowerLevel.add(spinnerResinPower, "cell 1 1,growx");
		spinnerOvercoatPower.setEnabled(false);
		panelPowerLevel.add(spinnerOvercoatPower, "cell 2 1,growx");

		panelPowerLevel.add(btnPowerLevel, "cell 0 2 3 1,alignx center");
		btnPowerLevel.setActionCommand(POWERLEVEL);
		btnPowerLevel.addActionListener(ah);

		// ===== Resin Area =====
		panelDriver1.add(panelResinArea, "cell 0 3,grow");
		panelResinArea.setLayout(new MigLayout("", "[grow][grow][grow][grow]", "[][][][]"));
		panelResinArea.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
								                  "", 
								                  TitledBorder.LEADING, 
								                  TitledBorder.TOP, 
								                  null, 
								                  new Color(0, 0, 0)));
		panelResinArea.add(labelResinSide, "flowx,cell 0 0 2 1,alignx left");
		panelResinArea.add(comboResinAreaSide, "cell 0 0 2 1,growx");
		comboResinAreaSide.addItem(new ComboItem("Front", Side.FRONT));
		comboResinAreaSide.addItem(new ComboItem("Back", Side.BACK));
		comboResinAreaSide.setActionCommand(RASIDE);
		comboResinAreaSide.addActionListener(ah); 
		
		panelResinArea.add(labelResinAreaNo, "cell 2 0,alignx right");
		panelResinArea.add(spinnerResinAreaNo, "cell 3 0,growx");
		spinnerResinAreaNo.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				ResinAreaChanged();
			}
	    });

		panelResinArea.add(labelResinL, "cell 0 1,alignx center");
		panelResinArea.add(labelResinW, "cell 1 1,alignx center");
		panelResinArea.add(labelResinB, "cell 2 1,alignx center");
		panelResinArea.add(labelResinH, "cell 3 1,alignx center");
		spinnerResinL.setEnabled(false);
		spinnerResinL.setEditor(new JSpinner.NumberEditor(spinnerResinL,"#"));
		panelResinArea.add(spinnerResinL, "cell 0 2,growx");
		spinnerResinW.setEnabled(false);
		spinnerResinW.setEditor(new JSpinner.NumberEditor(spinnerResinW,"#"));
		panelResinArea.add(spinnerResinW, "cell 1 2,growx");
		spinnerResinB.setEnabled(false);
		spinnerResinB.setEditor(new JSpinner.NumberEditor(spinnerResinB,"#"));
		panelResinArea.add(spinnerResinB, "cell 2 2,growx");
		spinnerResinH.setEnabled(false);
		spinnerResinH.setEditor(new JSpinner.NumberEditor(spinnerResinH,"#"));
		panelResinArea.add(spinnerResinH, "cell 3 2,growx");

		panelResinArea.add(btnResinArea, "cell 0 3 4 1,alignx center");
		btnResinArea.setActionCommand(RESINAREA);
		btnResinArea.addActionListener(ah);

		// ===== Area/Hole =====
		panelDriver1.add(panelAreaHole, "cell 0 4,grow");
		panelAreaHole.setLayout(new MigLayout("", "[grow][grow][grow][grow][grow]", "[][][][][]"));
		panelAreaHole.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
								                 "", 
								                 TitledBorder.LEADING, 
								                 TitledBorder.TOP, 
								                 null, 
								                 new Color(0, 0, 0)));
		panelAreaHole.add(labelAreaHoleSide, "flowx,cell 0 0");
		panelAreaHole.add(comboAreaHoleSide, "cell 1 0 2 1,growx");
		comboAreaHoleSide.addItem(new ComboItem("Front", Side.FRONT));
		comboAreaHoleSide.addItem(new ComboItem("Back", Side.BACK));
		comboAreaHoleSide.setActionCommand(AHSIDE);
		comboAreaHoleSide.addActionListener(ah);

		panelAreaHole.add(labelAreaHoleType, "flowx,cell 0 1");
		panelAreaHole.add(comboAreaHoleType, "cell 1 1 2 1,growx");
		comboAreaHoleType.addItem(new ComboItem("Area", AreaHole.AREA));
		comboAreaHoleType.addItem(new ComboItem("Hole", AreaHole.HOLE));
		comboAreaHoleType.setActionCommand(AHTYPE);
		comboAreaHoleType.addActionListener(ah);

		panelAreaHole.add(labelAreaHoleNo, "cell 3 1,alignx right");
		panelAreaHole.add(spinnerAreaHoleNo, "cell 4 1,growx");
		spinnerAreaHoleNo.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				AreaHoleChanged();
			}
	    });

		panelAreaHole.add(labelAreaHoleL, "cell 0 2 2 1,alignx center");
		spinnerAreaHoleL.setEnabled(false);
		spinnerAreaHoleL.setEditor(new JSpinner.NumberEditor(spinnerAreaHoleL,"#"));
		panelAreaHole.add(spinnerAreaHoleL, "cell 0 3 2 1,growx");

		panelAreaHole.add(labelAreaHoleW, "cell 2 2,alignx center");
		spinnerAreaHoleW.setEnabled(false);
		spinnerAreaHoleW.setEditor(new JSpinner.NumberEditor(spinnerAreaHoleW,"#"));
		panelAreaHole.add(spinnerAreaHoleW, "cell 2 3,growx");

		panelAreaHole.add(labelAreaHoleB, "cell 3 2,alignx center");
		spinnerAreaHoleB.setEnabled(false);
		spinnerAreaHoleB.setEditor(new JSpinner.NumberEditor(spinnerAreaHoleB,"#"));
		panelAreaHole.add(spinnerAreaHoleB, "cell 3 3,growx");

		panelAreaHole.add(labelAreaHoleH, "cell 4 2,alignx center");
		spinnerAreaHoleH.setEnabled(false);
		spinnerAreaHoleH.setEditor(new JSpinner.NumberEditor(spinnerAreaHoleH,"#"));
		panelAreaHole.add(spinnerAreaHoleH, "cell 4 3,growx");

		panelAreaHole.add(btnAreaHole, "cell 0 4 5 1,alignx center");
		btnAreaHole.setActionCommand(AREAHOLE);
		btnAreaHole.addActionListener(ah);

		// ===== Rewritable =====
		panelDriver1.add(panelRewritable, "cell 0 5 1 2,grow");
		panelRewritable.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
								                   "", 
								                   TitledBorder.LEADING,	
								                   TitledBorder.TOP, 
								                   null, 
								                   new Color(0, 0, 0)));
		panelRewritable.setLayout(new MigLayout("", "[grow][grow][grow][grow]", "[][][][][][]"));
		panelRewritable.add(labelL, "cell 0 0,alignx center");
		panelRewritable.add(labelW, "cell 1 0,alignx center");
		panelRewritable.add(labelB, "cell 2 0,alignx center");
		panelRewritable.add(labelH, "cell 3 0,alignx center");

		spinnerEraseAreaL.setEnabled(false);
		spinnerEraseAreaL.setEditor(new JSpinner.NumberEditor(spinnerEraseAreaL,"#"));
		panelRewritable.add(spinnerEraseAreaL, "cell 0 1,growx");
		spinnerEraseAreaW.setEnabled(false);
		spinnerEraseAreaW.setEditor(new JSpinner.NumberEditor(spinnerEraseAreaW,"#"));
		panelRewritable.add(spinnerEraseAreaW, "cell 1 1,growx");
		spinnerEraseAreaB.setEnabled(false);
		spinnerEraseAreaB.setEditor(new JSpinner.NumberEditor(spinnerEraseAreaB,"#"));
		panelRewritable.add(spinnerEraseAreaB, "cell 2 1,growx");
		spinnerEraseAreaH.setEnabled(false);
		spinnerEraseAreaH.setEditor(new JSpinner.NumberEditor(spinnerEraseAreaH,"#"));
		panelRewritable.add(spinnerEraseAreaH, "cell 3 1,growx");

		panelRewritable.add(labelPower, "cell 0 2");
		panelRewritable.add(labelWritePower, "cell 0 3");
		spinnerEraseWrite.setEnabled(false);
		panelRewritable.add(spinnerEraseWrite, "cell 1 3,growx");

		checkEraseBeforePrint.setEnabled(false);
		panelRewritable.add(checkEraseBeforePrint, "cell 2 3 2 1,alignx right");

		panelRewritable.add(labelStartPower, "cell 0 4");
		spinnerEraseStart.setEnabled(false);
		panelRewritable.add(spinnerEraseStart, "cell 1 4,growx");

		panelRewritable.add(labelEndPower, "cell 2 4");
		spinnerEraseEnd.setEnabled(false);
		panelRewritable.add(spinnerEraseEnd, "cell 3 4,growx");

		panelRewritable.add(btnRewritable, "cell 0 5 4 1,alignx center");
		btnRewritable.setActionCommand(REWRITABLE);
		btnRewritable.addActionListener(ah);

		// ===== Printable Area =====
		panelDriver1.add(panelPrintableArea, "cell 1 1,grow");
		panelPrintableArea.setLayout(new MigLayout("", "[grow][grow][grow][grow]", "[grow][grow][grow]"));
		panelPrintableArea.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
					                                  "", 
										              TitledBorder.LEADING, 
										              TitledBorder.TOP, 
										              null, 
										              new Color(0, 0, 0)));
		panelPrintableArea.add(labelPrintableAreaL, "cell 0 0,alignx center");
		spinnerPrintableAreaL.setEnabled(false);
		spinnerPrintableAreaL.setEditor(new JSpinner.NumberEditor(spinnerPrintableAreaL,"#"));
		panelPrintableArea.add(spinnerPrintableAreaL, "cell 1 0,growx");
		panelPrintableArea.add(labelPrintableAreaB, "cell 2 0,alignx center");
		spinnerPrintableAreaB.setEnabled(false);
		spinnerPrintableAreaB.setEditor(new JSpinner.NumberEditor(spinnerPrintableAreaB,"#"));
		panelPrintableArea.add(spinnerPrintableAreaB, "cell 3 0,growx");
		panelPrintableArea.add(labelPrintableAreaW, "cell 0 1,alignx center");
		spinnerPrintableAreaW.setEnabled(false);
		spinnerPrintableAreaW.setEditor(new JSpinner.NumberEditor(spinnerPrintableAreaW,"#"));
		panelPrintableArea.add(spinnerPrintableAreaW, "cell 1 1,growx");
		panelPrintableArea.add(labelPrintableAreaH, "cell 2 1,alignx center");
		spinnerPrintableAreaH.setEnabled(false);
		spinnerPrintableAreaH.setEditor(new JSpinner.NumberEditor(spinnerPrintableAreaH,"#"));
		panelPrintableArea.add(spinnerPrintableAreaH, "cell 3 1,growx");

		panelPrintableArea.add(btnPrintableArea, "cell 0 2 4 1,alignx center");
		btnPrintableArea.setActionCommand(PRINTABLEAREA);
		btnPrintableArea.addActionListener(ah);
		
		// ===== Resolution =====
		panelDriver1.add(panelResolution, "cell 1 2,grow");
		panelResolution.setLayout(new MigLayout("", "[grow][grow][grow]", "[][][]"));
		panelResolution.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
                                                   "", 
	                                               TitledBorder.LEADING, 
	                                               TitledBorder.TOP, 
	                                               null, 
	                                               new Color(0, 0, 0)));
		rdbtn300DPI.setEnabled(false);
		panelResolution.add(rdbtn300DPI, "cell 0 0 3 1,alignx center");
		rdbtn600DPI.setEnabled(false);
		panelResolution.add(rdbtn600DPI, "cell 0 1 3 1,alignx center");
		btnResolution.setEnabled(false);
		panelResolution.add(btnResolution, "cell 1 2,alignx center");
		buttonGroupResolution.add(rdbtn300DPI);
		buttonGroupResolution.add(rdbtn600DPI);
		btnResolution.setActionCommand(RESOLUTION);
		btnResolution.addActionListener(ah);

		// ===== Text Area =====
		panelDriver1.add(scrollPane, "flowy,cell 1 3 1 3,grow");
		textDriver1Msg.setBorder(BorderFactory.createLineBorder(Color.black));

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

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

	void Init(HANDLE handle, SDKlib sdk) {
		tabbedPane.addTab(DRIVER1_TAB_TITLE, null, panelDriver1, null);
		this.hSession = handle;
		this.SDK = sdk;

		spinnerResinL.setModel(new SpinnerNumberModel(0, 0, maxXCoord, 1));
		spinnerResinW.setModel(new SpinnerNumberModel(0, 0, maxCardLength, 1));
		spinnerAreaHoleL.setModel(new SpinnerNumberModel(0, 0, maxXCoord, 1));
		spinnerAreaHoleW.setModel(new SpinnerNumberModel(0, 0, maxCardLength, 1));
		spinnerEraseAreaL.setModel(new SpinnerNumberModel(0, 0, maxXCoord, 1));
		spinnerEraseAreaW.setModel(new SpinnerNumberModel(0, 0, maxCardLength, 1));

		GetGUIControl(new GUIControl());
		GetSharpness(new ByteByReference());
		GetCorrection(new ByteByReference());
		GetResinArea(Side.FRONT, (byte)1, new Area());
		GetAreaHole(Side.FRONT, AreaHole.AREA, (byte)1, new Area());
		GetRewritable(new Rewritable());
		
		if (connectedPrinter == PrinterType.GENERATION2) {
			btnPrintSpeed.setVisible(false);
			comboPrintSpeed.setVisible(false);
			
			spinnerYMCPower.setModel(new SpinnerNumberModel(new Byte("0"), new Byte("-100"), new Byte("100"), new Byte("1")));
			spinnerResinPower.setModel(new SpinnerNumberModel(new Byte("0"), new Byte("-100"), new Byte("100"), new Byte("1")));
			spinnerOvercoatPower.setModel(new SpinnerNumberModel(new Byte("0"), new Byte("-100"), new Byte("100"), new Byte("1")));
		}
		else {
			btnPrintSpeed.setVisible(true);
			comboPrintSpeed.setVisible(true);

			GetPrintSpeed(new ByteByReference());
		}
		GetPowerLevels(new PowerLevel());
	}
	
    //====================================================================================

	void Selected() {
		if (PrinterIs600DPICapable())
        {
            ByteByReference resolution = new ByteByReference();
            GetResolution(resolution);
            btnResolution.setEnabled(true);
        }
	}
	
	// ------------------------------------------------------------------------------------

	static void InitCorrectionCombo(JComboBox<ComboItem> combo)	{
		combo.addItem(new ComboItem("None",              Correction.NONE));
		combo.addItem(new ComboItem("Gamma 1",           Correction.GAMMA1));
		combo.addItem(new ComboItem("Gamma 2",           Correction.GAMMA2));
		combo.addItem(new ComboItem("ICC Internal",      Correction.ICC_INTERNAL));
		combo.addItem(new ComboItem("ICC External",      Correction.ICC_EXTERNAL));
		combo.addItem(new ComboItem("Perceptual",        Correction.PERCEPTUAL));
		combo.addItem(new ComboItem("Saturation",        Correction.SATURATION));
		combo.addItem(new ComboItem("Rel. Colorimetric", Correction.REL_COLORIMETRIC));
		combo.addItem(new ComboItem("Abs. Colorimetric", Correction.ABS_COLORIMETRIC));
	}

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

	private void GetSetControls(Boolean State) {
		checkUser.setEnabled(State);
		checkPrinter.setEnabled(State);
		spinnerSharpness.setEnabled(State);
		comboCorrection.setEnabled(State);
		comboPrintSpeed.setEnabled(State);
		spinnerYMCPower.setEnabled(State);
		spinnerResinPower.setEnabled(State);
		spinnerOvercoatPower.setEnabled(State);
		spinnerResinL.setEnabled(State);
		spinnerResinW.setEnabled(State);
		spinnerResinB.setEnabled(State);
		spinnerResinH.setEnabled(State);
		spinnerAreaHoleL.setEnabled(State);
		spinnerAreaHoleW.setEnabled(State);
		spinnerAreaHoleB.setEnabled(State);
		spinnerAreaHoleH.setEnabled(State);
		spinnerEraseAreaL.setEnabled(State);
		spinnerEraseAreaW.setEnabled(State);
		spinnerEraseAreaB.setEnabled(State);
		spinnerEraseAreaH.setEnabled(State);
		spinnerEraseStart.setEnabled(State);
		spinnerEraseEnd.setEnabled(State);
		spinnerEraseWrite.setEnabled(State);
		checkEraseBeforePrint.setEnabled(State);

		switch (connectedPrinter)
        {
        case PrinterType.ENDURO:
        	comboPrintSpeed.setEnabled(State);
            break;
        case PrinterType.GENERATION2:
        	spinnerPrintableAreaL.setEnabled(State);
        	spinnerPrintableAreaW.setEnabled(State);
        	spinnerPrintableAreaB.setEnabled(State);
        	spinnerPrintableAreaH.setEnabled(State);

            if (PrinterIs600DPICapable())
            {
            	rdbtn300DPI.setEnabled(State);
            	rdbtn600DPI.setEnabled(State);
            }
            break;
        }
	}

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

    public boolean PrinterIs600DPICapable()
    {
        if (connectedPrinter != PrinterType.GENERATION2)
        {
	        return false;
        }

        return ((SDK.ID_PrinterModel(hSession)& Model.DPI600) != 0);
    }

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

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

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

	private void GUIControlToMsgBox(byte action, GUIControl GUI) {
		String sep = Separator(action);
		textDriver1Msg.append("GUI User"    + sep + EnabledDisabledString(GUI.user) + "\n" 
							+ "GUI Printer" + sep + EnabledDisabledString(GUI.printer) + "\n\n");
	}

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

	private byte GetGUIControl(GUIControl GUI) {
		byte sdkReturn = SDK.ID_GUIControl(hSession, Action.READ, GUI);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetGUIControl", sdkReturn);
		} 
		else {
			checkUser.setSelected(GUI.user);
			checkPrinter.setSelected(GUI.printer);
		}
		return sdkReturn;
	}

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

	private void GUIControl() {
		GUIControl GUI = new GUIControl();
		if (rdbtnGet.isSelected()) {
			if (GetGUIControl(GUI) == Return.SUCCESS) {
				GUIControlToMsgBox(Action.READ, GUI);
			}
		}
		else {
			GUI.user    = checkUser.isSelected();
			GUI.printer = checkPrinter.isSelected();

			byte sdkReturn = SDK.ID_GUIControl(hSession, Action.WRITE, GUI);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("SetGUIControl", sdkReturn);
			} 
			else {
				GUIControlToMsgBox(Action.WRITE, GUI);
			}
		}
	}

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

	private void SharpnessToMsgBox(byte action, byte sharpness) {
		textDriver1Msg.append("Sharpness" + Separator(action) + sharpness + "\n\n");
	}

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

	private byte GetSharpness(ByteByReference sharpness) {
		byte sdkReturn = SDK.ID_Sharpness(hSession, Action.READ, sharpness);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetSharpness", sdkReturn);
		} 
		else {
			spinnerSharpness.setValue(sharpness.getValue());
		}
		return sdkReturn;
	}

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

	private void Sharpness() {
		ByteByReference sharpness = new ByteByReference();
		if (rdbtnGet.isSelected()) {
			if (GetSharpness(sharpness) == Return.SUCCESS) {
				SharpnessToMsgBox(Action.READ, sharpness.getValue());
			}
		}
		else {
			sharpness.setValue((byte)spinnerSharpness.getValue());
			byte sdkReturn = SDK.ID_Sharpness(hSession, Action.WRITE, sharpness);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("SetSharpness", sdkReturn);
			}
			else {
				SharpnessToMsgBox(Action.WRITE, sharpness.getValue());
			}
		}
	}

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

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

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

	private void CorrectionToMsgBox(byte action, byte correction) {
		textDriver1Msg.append("Correction" 
							  + Separator(action) 
							  + CorrectionString(correction) 
							  + "\n\n");
	}

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

	private byte GetCorrection(ByteByReference correction) {
		byte sdkReturn = SDK.ID_ColourCorrection(hSession, Action.READ, correction);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetColourCorrection", sdkReturn);
		} 
		else {
			comboCorrection.setSelectedIndex(correction.getValue());
		}
		return sdkReturn;
	}

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

	private void ColourCorrection() {
		ByteByReference correction = new ByteByReference(
				((ComboItem)comboCorrection.getSelectedItem()).getValue());
		if (rdbtnGet.isSelected()) {
			if (GetCorrection(correction) == Return.SUCCESS) {
				CorrectionToMsgBox(Action.READ, correction.getValue());
			}
		}
		else {
			byte sdkReturn = SDK.ID_ColourCorrection(hSession, Action.WRITE, correction);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("SetColourCorrection", sdkReturn);
			}
			else {
				CorrectionToMsgBox(Action.WRITE, correction.getValue());
			}
		}
	}

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

	private void PowerLevelToMsgBox(byte action, PowerLevel Power) {
		String sep = Separator(action);
		textDriver1Msg.append(  "Power Level YMC"      + sep + Power.ymc      + "\n"
							  + "Power Level Resin"    + sep + Power.resin    + "\n"
							  + "Power Level Overcoat" + sep + Power.overcoat + "\n\n");
	}

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

	private byte GetPowerLevels(PowerLevel Power) {
		byte sdkReturn = SDK.ID_PowerLevel(hSession, Action.READ, Power);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetPowerLevel", sdkReturn);
		} 
		else {
			spinnerYMCPower.setValue(Power.ymc);
			spinnerResinPower.setValue(Power.resin);
			spinnerOvercoatPower.setValue(Power.overcoat);
		}
		return sdkReturn;
	}

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

	private void PowerLevel() {
		PowerLevel Power = new PowerLevel();
		if (rdbtnGet.isSelected()) {
			if (GetPowerLevels(Power) == Return.SUCCESS) {
				PowerLevelToMsgBox(Action.READ, Power);
			}
		}
		else {
			Power.ymc      = (byte)spinnerYMCPower.getValue();
			Power.resin    = (byte)spinnerResinPower.getValue();
			Power.overcoat = (byte)spinnerOvercoatPower.getValue();

			byte sdkReturn = SDK.ID_PowerLevel(hSession, Action.WRITE, Power);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("SetPowerLevel", sdkReturn);
			} 
			else {
				PowerLevelToMsgBox(Action.WRITE, Power);
			}
		}
	}

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

	private void PrintSpeedToMsgBox(byte action, byte speed) {
		textDriver1Msg.append("Print Speed" 
							  + Separator(action)
							  + (speed == PrintSpeed.HIGH ? "High": "Normal") 
							  + "\n\n");
	}

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

	private byte GetPrintSpeed(ByteByReference speed) {
		byte sdkReturn = SDK.ID_PrintSpeed(hSession, Action.READ, speed);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetPrintSpeed", sdkReturn);
		} 
		else {
			comboPrintSpeed.setSelectedIndex(speed.getValue());
		}
		return sdkReturn;
	}

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

	private void PrintSpeed() {
		ByteByReference speed = new ByteByReference(((ComboItem)comboPrintSpeed.getSelectedItem()).getValue());
		if (rdbtnGet.isSelected()) {
			if (GetPrintSpeed(speed) == Return.SUCCESS) {
				PrintSpeedToMsgBox(Action.READ, speed.getValue());
			}
		}
		else {
			byte sdkReturn = SDK.ID_PrintSpeed(hSession, Action.WRITE, speed);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("SetPrintSpeed", sdkReturn);
			}
			else {
				PrintSpeedToMsgBox(Action.WRITE, speed.getValue());
			}
		}
	}

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

	private void ResinAreaChanged() {
		Area RA = new Area();
		if (GetResinArea(((ComboItem)comboResinAreaSide.getSelectedItem()).getValue(), 
						 (byte)spinnerResinAreaNo.getValue(),
						 RA) == Return.SUCCESS) {
			ResinAreaDisplay(RA);
		}
	}

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

	private void ResinAreaDisplay(Area RA) {
		spinnerResinL.setValue(RA.left);
		spinnerResinW.setValue(RA.width);
		spinnerResinB.setValue(RA.bottom);
		spinnerResinH.setValue(RA.height);
	}

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

	private void ResinAreaToMsgBox(byte action, byte areaNo, byte side, Area RA) {
		String sep = Separator(action);
		textDriver1Msg.append("Resin Area " + ((ComboItem)comboResinAreaSide.getSelectedItem()).toString()
							  + " " + areaNo + "\n"
							  + "Left"   + sep + RA.left   + "\n" 
							  + "Width"  + sep + RA.width  + "\n" 
							  + "Bottom" + sep + RA.bottom + "\n" 
							  + "Height" + sep + RA.height + "\n\n");
	}

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

	private byte GetResinArea(byte side, byte areaNo, Area RA) {
		byte sdkReturn = SDK.ID_ResinArea(hSession, Action.READ, side, areaNo, RA);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetResinArea", sdkReturn);
		} 
		else {
			ResinAreaDisplay(RA);
		}
		return sdkReturn;
	}

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

	private void ResinArea() {
		Area RA = new Area();
		byte side   = ((ComboItem)comboResinAreaSide.getSelectedItem()).getValue();
		byte areaNo = (byte)spinnerResinAreaNo.getValue();

		if (rdbtnGet.isSelected()) {
			if (GetResinArea(side, areaNo, RA) == Return.SUCCESS) {
				ResinAreaToMsgBox(Action.READ, areaNo, side, RA);
			}
		}
		else {
			RA.left   = (int)spinnerResinL.getValue();
			RA.width  = (int)spinnerResinW.getValue();
			RA.bottom = (int)spinnerResinB.getValue();
			RA.height = (int)spinnerResinH.getValue();

			byte sdkReturn = SDK.ID_ResinArea(hSession, Action.WRITE, side, areaNo, RA);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("SetResinArea", sdkReturn);
			} 
			else {
				ResinAreaToMsgBox(Action.WRITE, areaNo, side, RA);
			}
		}
	}

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

	private void AreaHoleChanged() {
		Area RA = new Area();
		if (GetAreaHole(((ComboItem)comboAreaHoleSide.getSelectedItem()).getValue(), 
						((ComboItem)comboAreaHoleType.getSelectedItem()).getValue(), 
						(byte)spinnerAreaHoleNo.getValue(),
						RA) == Return.SUCCESS) {
			AreaHoleDisplay(RA);
		}
	}

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

	private void AreaHoleDisplay(Area RA) {
		spinnerAreaHoleL.setValue(RA.left);
		spinnerAreaHoleW.setValue(RA.width);
		spinnerAreaHoleB.setValue(RA.bottom);
		spinnerAreaHoleH.setValue(RA.height);
	}

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

	private void AreaHoleToMsgBox(byte action, byte side, byte type, byte areaNo, Area RA) {
		String sep = Separator(action);
		textDriver1Msg.append("Area/Hole " + ((ComboItem)comboAreaHoleSide.getSelectedItem()).toString()
							  + (type == AreaHole.HOLE ? " Hole " : " Area ") + areaNo + "\n"
							  + "Left"   + sep + RA.left   + "\n"
							  + "Width"  + sep + RA.width  + "\n" 
							  + "Bottom" + sep + RA.bottom + "\n" 
							  + "Height" + sep + RA.height + "\n\n");
	}

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

	private byte GetAreaHole(byte side, byte type, byte areaNo, Area RA) {
		byte sdkReturn = SDK.ID_AreaHole(hSession, Action.READ, side, type, areaNo, RA);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetAreaHole", sdkReturn);
		} 
		else {
			AreaHoleDisplay(RA);
		}
		return sdkReturn;
	}

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

	private void AreaHole() { 
		Area RA = new Area();
		byte side   = ((ComboItem)comboAreaHoleSide.getSelectedItem()).getValue();
		byte type   = ((ComboItem)comboAreaHoleType.getSelectedItem()).getValue();
		byte areaNo = (byte)spinnerResinAreaNo.getValue();

		if (rdbtnGet.isSelected()) {
			if (GetAreaHole(side, type, areaNo, RA) == Return.SUCCESS) {
				AreaHoleToMsgBox(Action.READ, side, type, areaNo, RA);
			}
		}
		else {
			RA.left   = (int)spinnerAreaHoleL.getValue();
			RA.width  = (int)spinnerAreaHoleW.getValue();
			RA.bottom = (int)spinnerAreaHoleB.getValue();
			RA.height = (int)spinnerAreaHoleH.getValue();

			byte sdkReturn = SDK.ID_AreaHole(hSession, Action.WRITE, side, type, areaNo, RA);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("SetAreaHole", sdkReturn);
			} 
			else {
				AreaHoleToMsgBox(Action.WRITE, side, type, areaNo, RA);
			}
		}
	}

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

	private void RewritableToMsgBox(byte action, Rewritable Rewrite) {
		String sep = Separator(action);
		textDriver1Msg.append("Erase Area" + sep 
							  + Rewrite.eraseArea.left   + ","
							  + Rewrite.eraseArea.width  + "," 
							  + Rewrite.eraseArea.bottom + "," 
							  + Rewrite.eraseArea.height + "\n" 
							  + "Erase Before Print" + sep + OnOffString(Rewrite.eraseBeforePrint) + "\n"
							  + "Erase Power Start"  + sep + Rewrite.erasePowerStart + "\n"
							  + "Erase Power End"    + sep + Rewrite.erasePowerEnd   + "\n"
							  + "Write Power"        + sep + Rewrite.writePower      + "\n\n");
	}

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

	private byte GetRewritable(Rewritable Rewrite) {
		byte sdkReturn = SDK.ID_Rewritable(hSession, Action.READ, Rewrite);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetRewritable", sdkReturn);
		} 
		else {
			spinnerEraseAreaL.setValue(Rewrite.eraseArea.left);
			spinnerEraseAreaW.setValue(Rewrite.eraseArea.width);
			spinnerEraseAreaB.setValue(Rewrite.eraseArea.bottom);
			spinnerEraseAreaH.setValue(Rewrite.eraseArea.height);
			checkEraseBeforePrint.setSelected(Rewrite.eraseBeforePrint);
			spinnerEraseStart.setValue(Rewrite.erasePowerStart);
			spinnerEraseEnd.setValue(Rewrite.erasePowerEnd);
			spinnerEraseWrite.setValue(Rewrite.writePower);
		}
		return sdkReturn;
	}

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

	private void Rewritable() {
		Rewritable Rewrite = new Rewritable();
		if (rdbtnGet.isSelected()) {
			if (GetRewritable(Rewrite) == Return.SUCCESS) {
				RewritableToMsgBox(Action.READ, Rewrite);
			}
		}
		else {
			Rewrite.eraseArea.left   = (int)spinnerEraseAreaL.getValue();
			Rewrite.eraseArea.width  = (int)spinnerEraseAreaW.getValue();
			Rewrite.eraseArea.bottom = (int)spinnerEraseAreaB.getValue();
			Rewrite.eraseArea.height = (int)spinnerEraseAreaH.getValue();
			Rewrite.eraseBeforePrint = checkEraseBeforePrint.isSelected();
			Rewrite.erasePowerStart  = (byte)spinnerEraseStart.getValue();
			Rewrite.erasePowerEnd    = (byte)spinnerEraseEnd.getValue();
			Rewrite.writePower       = (byte)spinnerEraseWrite.getValue();

			byte sdkReturn = SDK.ID_Rewritable(hSession, Action.WRITE, Rewrite);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("SetRewritable", sdkReturn);
			} 
			else {
				RewritableToMsgBox(Action.WRITE, Rewrite);
			}
		}
	}

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

	private void PrintableAreaDisplay(Area RA) {
		spinnerPrintableAreaL.setValue(RA.left);
		spinnerPrintableAreaW.setValue(RA.width);
		spinnerPrintableAreaB.setValue(RA.bottom);
		spinnerPrintableAreaH.setValue(RA.height);
	}

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

	private void PrintableAreaToMsgBox(byte action, Area RA) {
		String sep = Separator(action);
		textDriver1Msg.append("Printable Area "
							  + "Left"   + sep + RA.left   + "\n"
							  + "Width"  + sep + RA.width  + "\n" 
							  + "Bottom" + sep + RA.bottom + "\n" 
							  + "Height" + sep + RA.height + "\n\n");
	}

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

	private byte GetPrintableArea(Area RA) {
		byte sdkReturn = SDK.ID_PrintableArea(hSession, Action.READ, RA);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetPrintableArea", sdkReturn);
		} 
		else {
			PrintableAreaDisplay(RA);
		}
		return sdkReturn;
	}

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

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

		if (rdbtnGet.isSelected()) {
			if (GetPrintableArea(RA) == Return.SUCCESS) {
				PrintableAreaToMsgBox(Action.READ, RA);
			}
		}
		else {
			RA.left   = (int)spinnerPrintableAreaL.getValue();
			RA.width  = (int)spinnerPrintableAreaW.getValue();
			RA.bottom = (int)spinnerPrintableAreaB.getValue();
			RA.height = (int)spinnerPrintableAreaH.getValue();

			byte sdkReturn = SDK.ID_PrintableArea(hSession, Action.WRITE, RA);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("SetPrintableArea", sdkReturn);
			} 
			else {
				PrintableAreaToMsgBox(Action.WRITE, RA);
			}
		}
	}

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

    public byte GetResolution(ByteByReference resolution)
    {
        byte sdkReturn = SDK.ID_Resolution(hSession, Action.READ, resolution);
        if (sdkReturn == Return.SUCCESS)
        {
            SetResolution(resolution.getValue());
        }
        else
        {
        	DisplayError("GetResolution", sdkReturn);
        }
        return sdkReturn;
    }

    private void ResolutionToMsgBox(byte action, byte resolution)
    {
    	textDriver1Msg.append("Resolution" 
                              + Separator(action)
                              + (resolution != 0 ? "600" : "300")
                              + " x 300 DPI\n\n");
    }

    private void SetResolution(byte resolution)
    {
        if (resolution == 0)
        	rdbtn300DPI.setSelected(true);
        else
        	rdbtn600DPI.setSelected(true);
    }

    private void Resolution() { 
        ByteByReference resolution = new ByteByReference();

		if (rdbtnGet.isSelected()) {
            if (GetResolution(resolution) == Return.SUCCESS)
            {
                ResolutionToMsgBox(Action.READ, resolution.getValue());
            }
        }
        else
        {
            resolution.setValue((byte)(rdbtn600DPI.isSelected() ? 1 : 0));
            byte sdkReturn = SDK.ID_Resolution(hSession, Action.WRITE, resolution);
            if (sdkReturn != Return.SUCCESS)
            {
            	DisplayError("SetResolution", sdkReturn);
            }
            else
            {
                ResolutionToMsgBox(Action.WRITE, resolution.getValue());
            }
        }
    }

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

	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 GUICONTROL:    GUIControl();          break;
			case SHARPNESS:     Sharpness();           break;
			case COLOUR:        ColourCorrection();    break;
			case POWERLEVEL:    PowerLevel();          break;
			case PRINTSPEED:    PrintSpeed();          break;
			case RESINAREA:     ResinArea();           break;
			case RASIDE:        ResinAreaChanged();    break;
			case AREAHOLE:      AreaHole();            break;
			case AHSIDE:        AreaHoleChanged();     break;
			case AHTYPE:        AreaHoleChanged();     break;
			case REWRITABLE:    Rewritable();          break;
			case PRINTABLEAREA: PrintableArea();       break;
			case RESOLUTION:    Resolution();          break;
			}
		}
	}
}
