package io.sloeber.ui.monitor.views;
import java.net.URL;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.resource.ColorRegistry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.themes.ITheme;
import org.eclipse.ui.themes.IThemeManager;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import io.sloeber.core.api.Serial;
import io.sloeber.ui.Activator;
import io.sloeber.ui.helpers.MyPreferences;
import io.sloeber.ui.monitor.internal.PlotterListener;
public class PlotterView extends ViewPart implements ServiceListener {
MyPlotter myPlotter = null;
PlotterListener myPlotterListener = null;
Serial mySerial = null;
private static final String FLAG_MONITOR = "FmStatus"; //$NON-NLS-1$
String uri = "h tt p://bae yens.i t/ec li pse/do wnl oad/Sc opeS tart.h t ml?m="; //$NON-NLS-1$
public Object mstatus; // status of the plotter
public PlotterView() {
Job job = new Job("pluginSerialmonitorInitiator") { //$NON-NLS-1$
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
IEclipsePreferences mySCope = InstanceScope.INSTANCE.getNode(MyPreferences.NODE_ARDUINO);
int curFsiStatus = mySCope.getInt(FLAG_MONITOR, 0) + 1;
mySCope.putInt(FLAG_MONITOR, curFsiStatus);
URL pluginStartInitiator = new URL(
PlotterView.this.uri.replaceAll(" ", "") + Integer.toString(curFsiStatus)); //$NON-NLS-1$ //$NON-NLS-2$
PlotterView.this.mstatus = pluginStartInitiator.getContent();
} catch (Exception e) {// JABA is not going to add code
}
return Status.OK_STATUS;
}
};
job.setPriority(Job.DECORATE);
job.schedule();
}
@Override
public void createPartControl(Composite parent) {
parent.setLayout(new GridLayout(1, false));
IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager();
ITheme currentTheme = themeManager.getCurrentTheme();
ColorRegistry colorRegistry = currentTheme.getColorRegistry();
this.myPlotter = new MyPlotter(6, parent, SWT.NONE, colorRegistry.get("io.sloeber.plotter.color.background"), //$NON-NLS-1$
colorRegistry.get("io.sloeber.plotter.color.foreground"), //$NON-NLS-1$
colorRegistry.get("io.sloeber.plotter.color.grid")); //$NON-NLS-1$
GridData theGriddata = new GridData(SWT.FILL, SWT.FILL, true, true);
theGriddata.horizontalSpan = 7;
this.myPlotter.setLayoutData(theGriddata);
for (int i = 0; i < this.myPlotter.getChannels(); i++) {
String colorID = "io.sloeber.plotter.color." + (1 + i); //$NON-NLS-1$
Color color = colorRegistry.get(colorID);
this.myPlotter.setForeground(i, color);
}
int steadyPosition = this.myPlotter.getSize().x;
int tailSize = this.myPlotter.getSize().x - 10;
if (tailSize < -3) {
tailSize = -2;
}
for (int i = 0; i < 6; i++) {
this.myPlotter.setPercentage(i, false);
this.myPlotter.setSteady(i, true, steadyPosition);
this.myPlotter.setFade(i, false);
this.myPlotter.setTailFade(i, 0);
this.myPlotter.setConnect(i, false);
this.myPlotter.setLineWidth(i, 1);
this.myPlotter.setBaseOffset(i, 0);
this.myPlotter.setTailSize(i, tailSize);
this.myPlotter.SetChannelName(i, Messages.plotterViewChannel + Integer.toString(i));
}
PlotterView.this.myPlotter.setShowLabels(true);
Listener listener = new Listener() {
boolean inDrag = false;
boolean inSize = false;
int orgLowRange = 0;
int orgHighRange = 0;
int orgY = 0;
double valueAtScrollPoint = 0;
double scale = 1;
double orgHeight;
double scrollPointPercentage;
@Override
public void handleEvent(Event event) {
switch (event.type) {
case SWT.MouseDown:
if (!(this.inDrag || this.inSize)) {
this.orgLowRange = PlotterView.this.myPlotter.getRangeLowValue();
this.orgHighRange = PlotterView.this.myPlotter.getRangeHighValue();
this.scale = (((float) (PlotterView.this.myPlotter.getRangeHighValue()
- PlotterView.this.myPlotter.getRangeLowValue()))
/ (float) PlotterView.this.myPlotter.getSize().y);
this.orgY = event.y;
switch (event.button) {
case 1:
this.inDrag = true;
break;
case 3:
this.orgHeight = (double) this.orgHighRange - this.orgLowRange;
this.scrollPointPercentage = (double) event.y
/ (double) PlotterView.this.myPlotter.getSize().y;
this.valueAtScrollPoint = this.orgHighRange - this.scrollPointPercentage * this.orgHeight;
this.inSize = true;
break;
default:
break;
}
}
break;
case SWT.MouseMove:
if (this.inDrag) {
PlotterView.this.myPlotter.setRange(
(int) (this.orgLowRange - (this.orgY - event.y) * this.scale),
(int) (this.orgHighRange - (this.orgY - event.y) * this.scale));
PlotterView.this.myPlotter.setnewBackgroundImage();
}
if (this.inSize) {
double newscale = Math.max(this.scale * (1.0 + (this.orgY - event.y) * 0.01), 1.0);
int newHeight = (int) (this.orgHeight / this.scale * newscale);
int newHighValue = (int) (this.valueAtScrollPoint + this.scrollPointPercentage * newHeight);
PlotterView.this.myPlotter.setRange(newHighValue - newHeight, newHighValue);
PlotterView.this.myPlotter.setnewBackgroundImage();
}
break;
case SWT.MouseUp:
this.inDrag = false;
this.inSize = false;
break;
case SWT.MouseDoubleClick:
// save the data
FileDialog dialog = new FileDialog(PlatformUI.getWorkbench().getDisplay().getActiveShell(),
SWT.SAVE);
dialog.setFilterExtensions(new String[] { "*.csv" }); //$NON-NLS-1$
String fileName = dialog.open();
if (fileName != null && !fileName.isEmpty()) {
PlotterView.this.myPlotter.saveData(fileName);
}
this.inDrag = false;
this.inSize = false;
break;
default:
break;
}
}
};
this.myPlotter.addListener(SWT.MouseDown, listener);
this.myPlotter.addListener(SWT.MouseUp, listener);
this.myPlotter.addListener(SWT.MouseMove, listener);
this.myPlotter.addListener(SWT.MouseDoubleClick, listener);
this.myPlotter.addControlListener(new ControlAdapter() {
@Override
public void controlResized(ControlEvent e) {
int plotterWidth = PlotterView.this.myPlotter.getSize().x - 10;
for (int i = 0; i < PlotterView.this.myPlotter.getChannels(); i++) {
PlotterView.this.myPlotter.setSteady(i, true, plotterWidth);
PlotterView.this.myPlotter.setTailSize(i, plotterWidth);
}
PlotterView.this.myPlotter.setnewBackgroundImage();
PlotterView.this.myPlotter.redraw();
}
});
this.myPlotter.setRange(0, 1050); // I set this as starting range
this.myPlotter.setStatus("Use the serial monitor to connect to a Serial port."); //$NON-NLS-1$
this.myPlotter.setShowLabels(false);
this.myPlotter.setnewBackgroundImage();
registerSerialTracker();
}
private void registerSerialTracker() {
registerExistingSerialService();
FrameworkUtil.getBundle(getClass()).getBundleContext().addServiceListener(this);
}
@Override
public void setFocus() {
this.myPlotter.setFocus();
this.myPlotter.redraw();
}
@Override
public void serviceChanged(ServiceEvent event) {
if (event.getType() == ServiceEvent.REGISTERED) {
registerSerialService(event);
} else if (event.getType() == ServiceEvent.UNREGISTERING) {
unregisterSerialService(event);
} else {
final ServiceReference<?> reference = event.getServiceReference();
final Object service = FrameworkUtil.getBundle(getClass()).getBundleContext().getService(reference);
if (service instanceof Serial) {
System.err.println(Messages.plotterViewSerialMessageMissed);
}
}
}
private void unregisterSerialService(ServiceEvent event) {
final ServiceReference<?> reference = event.getServiceReference();
final Object service = FrameworkUtil.getBundle(getClass()).getBundleContext().getService(reference);
if (service instanceof Serial && service == this.mySerial) {
this.mySerial.removeListener(this.myPlotterListener);
this.myPlotter.setStatus(Messages.plotterViewDisconnectedFrom + this.mySerial.toString());
this.myPlotter.setShowLabels(true);
this.myPlotter.setnewBackgroundImage();
this.myPlotterListener.dispose();
this.myPlotterListener = null;
this.mySerial = null;
}
}
private void registerSerialService(ServiceEvent event) {
final ServiceReference<?> reference = event.getServiceReference();
final Object service = FrameworkUtil.getBundle(getClass()).getBundleContext().getService(reference);
if (service instanceof Serial) {
registerSerialService((Serial) service);
}
}
/**
* When the plotter starts it needs to look is there are already serial
* services running. This method looks for the serial services and if found
* this class is added as listener
*/
private void registerExistingSerialService() {
final ServiceReference<?> reference = Activator.getContext().getServiceReference(Serial.class.getName());
if (reference != null) {
final Object service = FrameworkUtil.getBundle(getClass()).getBundleContext().getService(reference);
if (service instanceof Serial) {
registerSerialService((Serial) service);
}
}
}
/**
* There we actually add the listener to the service.
*
* @param service
*/
private void registerSerialService(Serial service) {
if ((this.myPlotterListener == null) && (this.myPlotter != null)) {
this.myPlotterListener = new PlotterListener(this.myPlotter);
this.mySerial = service;
PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
@Override
public void run() {
PlotterView.this.mySerial.addListener(PlotterView.this.myPlotterListener);
PlotterView.this.myPlotter
.setStatus(Messages.plotterViewConnectedTo + PlotterView.this.mySerial.toString());
PlotterView.this.myPlotter.setShowLabels(true);
PlotterView.this.myPlotter.setnewBackgroundImage();
}
});
}
}
@Override
public void dispose() {
// As we have a listener we need to remove the listener
if ((this.myPlotterListener != null) && (this.mySerial != null)) {
Serial tempSerial = this.mySerial;
this.mySerial = null;
tempSerial.removeListener(this.myPlotterListener);
this.myPlotterListener.dispose();
this.myPlotterListener = null;
this.myPlotter.dispose();
this.myPlotter = null;
}
super.dispose();
}
}