package edu.fichte.pbi.ide.views; import java.io.File; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.part.ViewPart; import org.osgi.framework.Bundle; import edu.fichte.pbi.ide.Activator; import edu.fichte.pbi.util.CallbackVariableListener; import edu.fichte.pbi.vm.IRunWatcher; import edu.fichte.pbi.vm.Machine; import edu.fichte.pbi.vm.var.IVariable; public class DebugView extends ViewPart implements IRunWatcher { public static String ID = "edu.fichte.pbi.ide.debugView"; private Machine machine; //GUI elements private Label[] label = new Label[8]; private CLabel[] labelInOut = new CLabel[8]; private CLabel[] labelHighLow = new CLabel[8]; private Button[] buttonHighLow = new Button[8]; private Composite[] widgetPin = new Composite[8]; private StackLayout[] stackLayout = new StackLayout[8]; //load icons private Image imageHigh = loadIcon("status_red.gif"); private Image imageLow = loadIcon("status_black.gif"); private Image imageInput = loadIcon("InputArrowSmall.gif"); private Image imageOutput = loadIcon("OutputArrowSmall.gif"); @Override public void createPartControl(Composite parent) { //create layout Parent with GridLayout Composite layoutParent = new Composite(parent, 0); layoutParent.setLayout(new GridLayout(3, true)); //create Labels Label pin = new Label(layoutParent, 0); pin.setText("PIN"); Label io = new Label(layoutParent, 0); io.setText("I/O"); Label hl = new Label(layoutParent, 0); hl.setText("High/Low"); for (int i = widgetPin.length - 1; i >= 0; i--) { //first column: Pin Label label[i] = new Label(layoutParent, 0); label[i].setText("P" + String.valueOf(i)); //second column: Pin direction (Input/Output) labelInOut[i] = new CLabel(layoutParent, 0); labelInOut[i].setText("Input"); labelInOut[i].setImage(imageInput); //default is input, see: //(http://www.parallax.com/go/PBASICHelp/Content\ ///LanguageTopics/Commands/INPUT.htm -> Explanation) //third column: Pin state (High/Low) //changes between CLabel and Button, depending on if an //input is accepted or not (uses StackLayout for that) stackLayout[i] = new StackLayout(); //create new composite in which stackLayout is active widgetPin[i] = new Composite(layoutParent, 0); widgetPin[i].setLayout(stackLayout[i]); //create first "page" of stackLayout: label (if pin is output) labelHighLow[i] = new CLabel(widgetPin[i], 0); labelHighLow[i].setText("Low"); labelHighLow[i].setImage(imageLow); labelHighLow[i].pack(); //create second "page" of stackLayout: button (if pin is input) buttonHighLow[i] = new Button(widgetPin[i], 0); buttonHighLow[i].setText("Low"); buttonHighLow[i].setImage(imageLow); buttonHighLow[i].pack(); //show second "page" first as pin is initialized as input pin stackLayout[i].topControl = buttonHighLow[i]; //actions listeners are defined outside of the loop } //action listeners as you are not allowed to use //non-final variables in an inner class buttonHighLow[0].addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { toggleVariable(0); } }); buttonHighLow[1].addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { toggleVariable(1); } }); buttonHighLow[2].addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { toggleVariable(2); } }); buttonHighLow[3].addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { toggleVariable(3); } }); buttonHighLow[4].addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { toggleVariable(4); } }); buttonHighLow[5].addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { toggleVariable(5); } }); buttonHighLow[6].addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { toggleVariable(6); } }); buttonHighLow[7].addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { toggleVariable(7); } }); } @Override public void setFocus() { } private void toggleVariable(int varNum) { IVariable variable = machine.parseIVariable("PIN" + varNum); long value = variable.getValue(); if (value == 0) { value = 1; } else { value = 0; } variable.setValue(value); } public void setMachine(Machine machine) { this.machine = machine; IVariable[] listener = new IVariable[labelHighLow.length]; for (int i = 0; i < labelHighLow.length; i++) { listener[i] = this.machine.parseIVariable("PIN" + String.valueOf(i)); listener[i].setVariableListener( new CallbackVariableListener( new PinCommObject(labelHighLow[i], buttonHighLow[i])) { @Override public void variableChanged(IVariable variable) { final long value = variable.getValue(); final boolean[] newState = new boolean[1]; if (value == 1) { newState[0] = true; } getSite().getShell().getDisplay().syncExec(new Runnable() { @Override public void run() { PinCommObject obj = (PinCommObject) callback; if (newState[0]) { obj.label.setText("High"); obj.label.setImage(imageHigh); obj.button.setText("High"); obj.button.setImage(imageHigh); } else { obj.label.setText("Low"); obj.label.setImage(imageLow); obj.button.setText("Low"); obj.button.setImage(imageLow); } } }); } }); } IVariable[] dirListener = new IVariable[labelInOut.length]; for (int i = 0; i < labelInOut.length; i++) { dirListener[i] = this.machine.parseIVariable("DIR" + String.valueOf(i)); dirListener[i].setVariableListener( new CallbackVariableListener( new DirCommObject( labelInOut[i], labelHighLow[i], buttonHighLow[i], stackLayout[i], widgetPin[i])) { @Override public void variableChanged(IVariable variable) { final long value = variable.getValue(); final boolean[] newState = new boolean[1]; if (value == 1) { newState[0] = true; } getSite().getShell().getDisplay().syncExec( new Runnable() { @Override public void run() { DirCommObject obj = (DirCommObject) callback; if (newState[0]) { obj.labelDir.setText("Output"); obj.labelDir.pack(); obj.labelDir.setImage(imageOutput); obj.labelState.setVisible(true); obj.buttonState.setVisible(false); obj.stackLayout.topControl = obj.labelState; } else { obj.labelDir.setText("Input"); obj.labelDir.pack(); obj.labelDir.setImage(imageInput); obj.labelState.setVisible(false); obj.buttonState.setVisible(true); obj.stackLayout.topControl = obj.buttonState; } obj.widgetPin.layout(); } }); } }); } } private static Image loadIcon(String iconFilename) { Bundle bundle = Activator.getDefault().getBundle(); File targetRoot = bundle.getDataFile(""); File file = new File(targetRoot, "icons/" + iconFilename); if (!file.canRead()) { HelpView.copyPathFromBundleToFSRecursive(bundle, "icons", targetRoot); } return new Image(Display.getCurrent(), file.getAbsolutePath()); } public void lockPinState() { for (int i = 0; i < buttonHighLow.length; i++) { buttonHighLow[i].setEnabled(false); } } public void unlockPinState() { for (int i = 0; i < buttonHighLow.length; i++) { buttonHighLow[i].setEnabled(true); } } private class PinCommObject { protected CLabel label; protected Button button; private PinCommObject(CLabel label, Button button) { this.label = label; this.button = button; } } private class DirCommObject { protected CLabel labelDir; protected CLabel labelState; protected Button buttonState; protected StackLayout stackLayout; protected Composite widgetPin; private DirCommObject( CLabel labelDir, CLabel labelState, Button buttonState, StackLayout stackLayout, Composite widgetPin) { this.labelDir = labelDir; this.labelState = labelState; this.buttonState = buttonState; this.stackLayout = stackLayout; this.widgetPin = widgetPin; } } }