Merge "First cut at pulling in riolog plugin."

This commit is contained in:
Brad Miller (WPI)
2014-11-12 12:22:04 -08:00
committed by Gerrit Code Review
11 changed files with 577 additions and 1 deletions

View File

@@ -52,4 +52,11 @@
version="0.0.0"
unpack="false"/>
<plugin
id="edu.wpi.first.wpilib.plugins.riolog"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
</feature>

View File

@@ -0,0 +1,11 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: WPILib_Riolog
Bundle-SymbolicName: edu.wpi.first.wpilib.plugins.riolog;singleton:=true
Bundle-Version: 0.1.0.qualifier
Bundle-Activator: netconsole2.Activator
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ActivationPolicy: lazy
Bundle-Vendor: WPI & FIRST

View File

@@ -0,0 +1,13 @@
Riolog
This is an Eclipse plugin that receives and displays text from UDP port 6666. It
defines a new view that displays the received text.
To compile, open project in an Eclipse instance with the appropriate plugin
development tools, and Export as a deployable plugin/fragment.
To install, copy the resulting jar file into $eclipse/dropins/, and start
Eclipse (-clean may be necessary).
To enable, go to Window>Show View>Other... and choose General>Riolog.

View File

@@ -0,0 +1,7 @@
source.. = src/
output.. = bin/
bin.includes = plugin.xml,\
META-INF/,\
.,\
icons/,\
contexts.xml

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<contexts>
<context id="text" title="Riolog">
<description>This is the context help for the Riolog It was generated by a PDE template.</description>
<topic href="/PLUGINS_ROOT/org.eclipse.platform.doc.isv/guide/ua_help_context.htm" label="Context-sensitive help">
<enablement>
<with variable="platform">
<test property="org.eclipse.core.runtime.isBundleInstalled" args="org.eclipse.platform.doc.isv"/>
</with>
</enablement>
</topic>
</context>
</contexts>

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
<extension
point="org.eclipse.ui.views">
<view
name="Riolog"
icon="icons/riolog.png"
category="org.eclipse.ui"
class="netconsole2.views.RiologView"
id="netconsole2.views.RiologView">
</view>
</extension>
<extension
point="org.eclipse.ui.perspectiveExtensions">
<perspectiveExtension
targetID="org.eclipse.jdt.ui.JavaPerspective">
<view
ratio="0.5"
relative="org.eclipse.ui.views.ProblemView"
relationship="right"
id="netconsole2.views.RiologView">
</view>
</perspectiveExtension>
</extension>
<extension
point="org.eclipse.help.contexts">
<contexts
file="contexts.xml">
</contexts>
</extension>
</plugin>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<artifactId>edu.wpi.first.wpilib.plugins.riolog</artifactId>
<packaging>eclipse-plugin</packaging>
<parent>
<groupId>edu.wpi.first.wpilib.plugins</groupId>
<artifactId>edu.wpi.first.wpilib.plugins</artifactId>
<version>0.1.0.qualifier</version>
<relativePath>..</relativePath>
</parent>
</project>

View File

@@ -0,0 +1,61 @@
package netconsole2;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
/**
* The activator class controls the plug-in life cycle
*/
public class Activator extends AbstractUIPlugin {
// The plug-in ID
public static final String PLUGIN_ID = "riolog"; //$NON-NLS-1$
// The shared instance
private static Activator plugin;
/**
* The constructor
*/
public Activator() {
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception {
plugin = null;
super.stop(context);
}
/**
* Returns the shared instance
*
* @return the shared instance
*/
public static Activator getDefault() {
return plugin;
}
/**
* Returns an image descriptor for the image file at the given
* plug-in relative path
*
* @param path the path
* @return the image descriptor
*/
public static ImageDescriptor getImageDescriptor(String path) {
return imageDescriptorFromPlugin(PLUGIN_ID, path);
}
}

View File

@@ -0,0 +1,414 @@
package netconsole2.views;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
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.Menu;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
public class RiologView extends ViewPart {
public static Action confAction(String name, String tooltip, String img,
Action e) {
e.setText(name);
e.setToolTipText(tooltip);
e.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages()
.getImageDescriptor(img));
return e;
}
public static byte[] getPacket(DatagramSocket socket, DatagramPacket buf) {
try {
socket.receive(buf);
} catch (IOException e) {
return null;
}
byte[] ret = new byte[buf.getLength()];
System.arraycopy(buf.getData(), 0, ret, 0, ret.length);
return ret;
}
public static DatagramSocket makeRecvSocket() {
DatagramSocket socket = null;
try {
socket = new DatagramSocket(null);
socket.setReuseAddress(true);
socket.bind(new InetSocketAddress(6666));
} catch (SocketException e) {
e.printStackTrace();
socket.close();
return null;
}
return socket;
}
public static Thread startDaemonThread(Runnable r, String name) {
Thread t = new Thread(r, name);
t.setDaemon(true);
t.start();
return t;
}
/**
* The ID of the view as specified by the extension.
*/
public static final String ID = "netconsole2.views.RiologView";
Text text;
Thread listener;
Thread transferer;
volatile DatagramSocket socket_hook = null;
volatile boolean discard = false;
volatile boolean paused = false;
volatile boolean cleanup = false;
private Action clearAction;
private Action pauseAction;
private Action discardAction;
private Action unpauseAction;
private Action undiscardAction;
private Button discardButton;
private Button pauseButton;
/**
* The constructor.
*/
public RiologView() {
}
private void contributeToActionBars() {
IActionBars bars = getViewSite().getActionBars();
fillLocalPullDown(bars.getMenuManager());
fillLocalToolBar(bars.getToolBarManager());
}
/**
* This is a callback that will allow us to create the viewer and initialize
* it.
*/
public void createPartControl(Composite parent) {
GridLayout glayout = new GridLayout();
glayout.numColumns = 1;
parent.setLayout(glayout);
text = new Text(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL
| SWT.READ_ONLY);
{
GridData gdata = new GridData();
gdata.grabExcessVerticalSpace = true;
gdata.grabExcessHorizontalSpace = true;
gdata.horizontalAlignment = SWT.FILL;
gdata.verticalAlignment = SWT.FILL;
text.setLayoutData(gdata);
}
Composite row = new Composite(parent, SWT.NONE);
row.setLayout(new FillLayout(SWT.HORIZONTAL));
{
GridData gdata = new GridData();
gdata.grabExcessVerticalSpace = false;
gdata.grabExcessHorizontalSpace = true;
gdata.horizontalAlignment = SWT.FILL;
gdata.verticalAlignment = SWT.CENTER;
row.setLayoutData(gdata);
}
// Create the help context id for the viewer's control
PlatformUI.getWorkbench().getHelpSystem()
.setHelp(parent, "netconsole2.text");
makeActions();
makeButtons(row);
hookContextMenu();
contributeToActionBars();
startListening();
}
public void makeButtons(Composite parent) {
pauseButton = new Button(parent, SWT.TOGGLE);
pauseButton.setText(pauseAction.getText());
pauseButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (pauseButton.getSelection()) {
pauseAction.run();
} else {
unpauseAction.run();
}
}
});
discardButton = new Button(parent, SWT.TOGGLE);
discardButton.setText(discardAction.getText());
discardButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (discardButton.getSelection()) {
discardAction.run();
} else {
undiscardAction.run();
}
}
});
Button clearButton = new Button(parent, SWT.PUSH);
clearButton.setText(clearAction.getText());
clearButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
clearAction.run();
}
});
}
@Override
public void dispose() {
stopListening();
super.dispose();
}
private void fillContextMenu(IMenuManager manager) {
manager.add(pauseAction);
manager.add(unpauseAction);
manager.add(new Separator());
manager.add(clearAction);
manager.add(new Separator());
manager.add(discardAction);
manager.add(undiscardAction);
manager.add(new Separator());
manager.add(confAction("Copy", "Copy selected text",
ISharedImages.IMG_TOOL_COPY, new Action() {
@Override
public void run() {
text.copy();
}
}));
manager.add(confAction("Select All", "Select all text", "",
new Action() {
@Override
public void run() {
text.selectAll();
}
}));
}
private void fillLocalPullDown(IMenuManager manager) {
manager.add(pauseAction);
manager.add(unpauseAction);
manager.add(new Separator());
manager.add(clearAction);
manager.add(new Separator());
manager.add(discardAction);
manager.add(undiscardAction);
}
private void fillLocalToolBar(IToolBarManager manager) {
manager.add(pauseAction);
manager.add(unpauseAction);
manager.add(new Separator());
manager.add(clearAction);
manager.add(new Separator());
manager.add(discardAction);
manager.add(undiscardAction);
}
private void hookContextMenu() {
MenuManager menuMgr = new MenuManager("#PopupMenu");
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
RiologView.this.fillContextMenu(manager);
}
});
Menu menu = menuMgr.createContextMenu(text);
text.setMenu(menu);
}
private void makeActions() {
clearAction = confAction("Clear Log", "Empty the textbox",
ISharedImages.IMG_ETOOL_CLEAR, new Action() {
public void run() {
text.setText("");
}
});
pauseAction = confAction("Pause Display",
"Stop adding packets to the textbox",
ISharedImages.IMG_ELCL_STOP, new Action() {
public void run() {
pauseAction.setEnabled(false);
unpauseAction.setEnabled(true);
pauseButton.setSelection(true);
pauseButton.setText("Show 0 Packets");
paused = true;
}
});
pauseAction.setEnabled(true);
unpauseAction = confAction("Continue Display",
"Continue adding packets to the textbox",
ISharedImages.IMG_TOOL_FORWARD, new Action() {
public void run() {
paused = false;
transferer.interrupt();
pauseAction.setEnabled(true);
unpauseAction.setEnabled(false);
pauseButton.setSelection(false);
pauseButton.setText(pauseAction.getText());
}
});
unpauseAction.setEnabled(false);
discardAction = confAction("Discard Incoming",
"Drop all incoming packets", ISharedImages.IMG_ETOOL_DELETE,
new Action() {
public void run() {
discard = true;
discardAction.setEnabled(false);
undiscardAction.setEnabled(true);
discardButton.setSelection(true);
discardButton.setText(undiscardAction.getText());
}
});
discardAction.setEnabled(true);
undiscardAction = confAction("Accept Incoming",
"Accept all incoming packets", ISharedImages.IMG_OBJ_ADD,
new Action() {
public void run() {
discard = false;
discardAction.setEnabled(true);
undiscardAction.setEnabled(false);
discardButton.setSelection(false);
discardButton.setText(discardAction.getText());
}
});
undiscardAction.setEnabled(false);
}
/**
* Passing the focus request to the viewer's control.
*/
public void setFocus() {
text.setFocus();
}
public static String drainToString(ArrayList<byte[]> arr) {
int netlength = 0;
for (byte[] b : arr) {
netlength += b.length;
}
byte[] sum = new byte[netlength];
int mark = 0;
for (int i=0;i<arr.size();i++) {
byte[] b = arr.get(i);
System.arraycopy(b, 0, sum, mark, b.length);
arr.set(i, null);
mark += b.length;
}
arr.clear();
return new String(sum);
}
void startListening() {
final BlockingQueue<byte[]> queue = new LinkedBlockingQueue<>();
listener = startDaemonThread(new Runnable() {
@Override
public void run() {
DatagramSocket socket = makeRecvSocket();
if (socket == null)
return;
socket_hook = socket;
byte[] buf = new byte[4096];
DatagramPacket datagram = new DatagramPacket(buf, buf.length);
while (!Thread.interrupted()) {
byte[] s = getPacket(socket, datagram);
if (s != null && !discard) {
try {
queue.put(s);
} catch (InterruptedException e) {
socket.close();
return;
}
}
}
socket.close();
}
}, "Riolog-Listener");
transferer = startDaemonThread(new Runnable() {
@Override
public void run() {
final ArrayList<byte[]> temp = new ArrayList<>();
while (!cleanup) {
try {
temp.add(queue.take());
} catch (InterruptedException e) {
if (cleanup) {
return;
}
}
queue.drainTo(temp);
if (!paused) {
Display.getDefault().syncExec(new Runnable() {
@Override
public void run() {
if (text.isDisposed())
return;
text.append(drainToString(temp));
}
});
} else {
Display.getDefault().syncExec(new Runnable() {
@Override
public void run() {
if (paused) {
if (temp.size() == 1) {
pauseButton.setText("Show 1 Packet\u2002");
} else {
pauseButton.setText("Show " + String.valueOf(temp.size()) + " Packets");
}
}
}
});
}
}
}
}, "Riolog-Transfer");
}
void stopListening() {
cleanup = true;
if (socket_hook != null) {
socket_hook.close();
}
listener.interrupt();
transferer.interrupt();
}
}

View File

@@ -14,12 +14,13 @@
<module>edu.wpi.first.wpilib.plugins.cpp.feature</module>
<module>edu.wpi.first.wpilib.plugins.java</module>
<module>edu.wpi.first.wpilib.plugins.java.feature</module>
<module>edu.wpi.first.wpilib.plugins.riolog</module>
<module>edu.wpi.first.wpilib.plugins.updatesite</module>
</modules>
<properties>
<!-- local-repository>C:/Users/wpilibj-buildmaster/maven-repository</local-repository-->
<tycho-version>0.18.1</tycho-version>
<tycho-version>0.21.0</tycho-version>
</properties>
<repositories>