mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-28 02:11:43 +00:00
First cut at pulling in riolog plugin.
Plugin was retrieved from https://github.com/mstoeckl/riolog.git with minimal changes to make it compile. Change-Id: I340d77c69fe7598595deeaba8d4cd9414b971399
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user