| /******************************************************************************* |
| * Copyright (c) 2010 Boeing. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Boeing - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.ote.ui.message.watch; |
| |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Map; |
| import java.util.concurrent.Executor; |
| import java.util.concurrent.ExecutorService; |
| import java.util.concurrent.Executors; |
| import java.util.logging.Level; |
| import org.eclipse.core.runtime.jobs.Job; |
| 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.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.layout.GridDataFactory; |
| import org.eclipse.jface.viewers.DoubleClickEvent; |
| import org.eclipse.jface.viewers.IDoubleClickListener; |
| import org.eclipse.jface.viewers.ISelectionChangedListener; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.SelectionChangedEvent; |
| import org.eclipse.jface.viewers.TreeViewer; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.jface.wizard.WizardDialog; |
| import org.eclipse.nebula.widgets.xviewer.XViewer; |
| import org.eclipse.osee.connection.service.IServiceConnector; |
| import org.eclipse.osee.framework.jdk.core.util.benchmark.Benchmark; |
| import org.eclipse.osee.framework.logging.OseeLog; |
| import org.eclipse.osee.framework.plugin.core.util.Jobs; |
| import org.eclipse.osee.framework.plugin.core.util.OseeData; |
| import org.eclipse.osee.framework.ui.swt.Displays; |
| import org.eclipse.osee.framework.ui.swt.Widgets; |
| import org.eclipse.osee.ote.client.msg.IOteMessageService; |
| import org.eclipse.osee.ote.client.msg.core.IMessageSubscription; |
| import org.eclipse.osee.ote.message.MessageDefinitionProvider; |
| import org.eclipse.osee.ote.message.MessageProviderVersion; |
| import org.eclipse.osee.ote.message.interfaces.ITestEnvironmentMessageSystem; |
| import org.eclipse.osee.ote.message.tool.IUdpTransferListener; |
| import org.eclipse.osee.ote.message.tool.MessageMode; |
| import org.eclipse.osee.ote.message.tool.TransferConfig; |
| import org.eclipse.osee.ote.service.ConnectionEvent; |
| import org.eclipse.osee.ote.service.IOteClientService; |
| import org.eclipse.osee.ote.service.ITestConnectionListener; |
| import org.eclipse.ote.ui.message.internal.Activator; |
| import org.eclipse.ote.ui.message.internal.SWTResourceManager; |
| import org.eclipse.ote.ui.message.internal.WatchImages; |
| import org.eclipse.ote.ui.message.messageXViewer.MessageXViewer; |
| import org.eclipse.ote.ui.message.tree.AbstractTreeNode; |
| import org.eclipse.ote.ui.message.tree.ElementNode; |
| import org.eclipse.ote.ui.message.tree.INodeVisitor; |
| import org.eclipse.ote.ui.message.tree.MessageNode; |
| import org.eclipse.ote.ui.message.tree.MessageWatchLabelProvider; |
| import org.eclipse.ote.ui.message.tree.RootNode; |
| import org.eclipse.ote.ui.message.tree.WatchList; |
| import org.eclipse.ote.ui.message.tree.WatchedElementNode; |
| import org.eclipse.ote.ui.message.tree.WatchedMessageNode; |
| import org.eclipse.ote.ui.message.util.ClientMessageServiceTracker; |
| import org.eclipse.ote.ui.message.util.IOteMessageClientView; |
| import org.eclipse.ote.ui.message.watch.action.ClearUpdatesAction; |
| import org.eclipse.ote.ui.message.watch.action.ConvertWritersToReadersAction; |
| import org.eclipse.ote.ui.message.watch.action.DeleteSelectionAction; |
| import org.eclipse.ote.ui.message.watch.action.SendMessageAction; |
| import org.eclipse.ote.ui.message.watch.action.SetDataSourceMenu; |
| import org.eclipse.ote.ui.message.watch.action.SetMessageModeMenu; |
| import org.eclipse.ote.ui.message.watch.action.SetValueAction; |
| import org.eclipse.ote.ui.message.watch.action.WatchElementAction; |
| import org.eclipse.ote.ui.message.watch.action.ZeroizeElementAction; |
| import org.eclipse.ote.ui.message.watch.action.ZeroizeMessageAction; |
| import org.eclipse.ote.ui.message.watch.recording.RecordingWizard; |
| import org.eclipse.ote.ui.message.watch.recording.xform.CsvTransform; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.SashForm; |
| import org.eclipse.swt.dnd.Clipboard; |
| import org.eclipse.swt.dnd.DND; |
| import org.eclipse.swt.dnd.FileTransfer; |
| import org.eclipse.swt.dnd.TextTransfer; |
| import org.eclipse.swt.dnd.Transfer; |
| import org.eclipse.swt.events.DisposeEvent; |
| import org.eclipse.swt.events.DisposeListener; |
| import org.eclipse.swt.events.KeyEvent; |
| import org.eclipse.swt.events.KeyListener; |
| import org.eclipse.swt.events.MouseAdapter; |
| import org.eclipse.swt.events.MouseEvent; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.events.SelectionListener; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.GC; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.graphics.RGB; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.layout.RowLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.swt.widgets.FileDialog; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Listener; |
| import org.eclipse.swt.widgets.Menu; |
| import org.eclipse.swt.widgets.Tree; |
| import org.eclipse.swt.widgets.TreeItem; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.part.ViewPart; |
| import org.osgi.framework.FrameworkUtil; |
| |
| /** |
| * A view that allows the monitoring of messages and their associated elements |
| * |
| * @author Ken J. Aguilar |
| */ |
| public final class WatchView extends ViewPart implements ITestConnectionListener, IOteMessageClientView { |
| public static final RGB COLOR_GOLDENROD = new RGB(255,193,37); |
| |
| private MessageXViewer treeViewer; |
| private final ClientMessageServiceTracker msgServiceTracker; |
| private Label statusTxt; |
| private Clipboard cb; |
| private final File watchFile; |
| private Button recordButton; |
| private final Benchmark benchMark = new Benchmark("Message Watch Update Time"); |
| |
| public static final String VIEW_ID = "org.eclipse.ote.ui.message.watch.WatchView"; |
| |
| private DetailsBox detailsBox; |
| final IUdpTransferListener recBtnListener = new IUdpTransferListener() { |
| |
| @Override |
| public void onTransferComplete(final TransferConfig config) { |
| OseeLog.log(Activator.class, Level.INFO, "file transfer complete"); |
| Displays.ensureInDisplayThread(new Runnable() { |
| @Override |
| public void run() { |
| openInfo("Message Recorder", |
| "Message recording file " + config.getFileName() + " is now ready for opening"); |
| } |
| }); |
| } |
| |
| @Override |
| public void onTransferException(final TransferConfig config, final Throwable t) { |
| OseeLog.log(Activator.class, Level.SEVERE, "problems writing to recorder output file " + config.getFileName(), |
| t); |
| Displays.ensureInDisplayThread(new Runnable() { |
| @Override |
| public void run() { |
| recordButton.setSelection(false); |
| openInfo("Message Recorder", |
| "An exception occurred while writing to recorder output file " + config.getFileName()); |
| } |
| }); |
| } |
| }; |
| |
| private IOteMessageService messageService = null; |
| |
| private final SelectionListener recBtnHandler = new SelectionListener() { |
| |
| ExecutorService executor = Executors.newSingleThreadExecutor(); |
| |
| @Override |
| public void widgetDefaultSelected(SelectionEvent e) { |
| widgetSelected(e); |
| } |
| |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| if (recordButton.getSelection()) { |
| |
| final RecordingWizard recordingWizard = new RecordingWizard(watchList); |
| final WizardDialog recdialog = new WizardDialog(Displays.getActiveShell(), recordingWizard); |
| int recResult = recdialog.open(); |
| if (Window.OK == recResult) { |
| executor.submit(new Runnable() { |
| |
| @Override |
| public void run() { |
| try { |
| saveWatchFile(); |
| messageService.startRecording(recordingWizard.getFileName(), |
| recordingWizard.getFilteredMessageRecordDetails()).addListener(recBtnListener); |
| } catch (FileNotFoundException ex) { |
| Display.getCurrent().asyncExec(new Runnable() { |
| @Override |
| public void run() { |
| MessageDialog.openError(Displays.getActiveShell(), "Recording Error", |
| "Failed to open file for writing. " + "Make sure its not being used by another application"); |
| recordButton.setSelection(false); |
| } |
| }); |
| } catch (Throwable ex) { |
| OseeLog.log(Activator.class, Level.SEVERE, "Failed to start message recording", ex); |
| Display.getCurrent().asyncExec(new Runnable() { |
| |
| @Override |
| public void run() { |
| MessageDialog.openError(Displays.getActiveShell(), "Recording Error", |
| "Exception ocurred while recording. see error log"); |
| recordButton.setSelection(false); |
| } |
| }); |
| } |
| } |
| }); |
| } else { |
| recordButton.setSelection(false); |
| } |
| } else { |
| executor.submit(new Runnable() { |
| |
| @Override |
| public void run() { |
| try { |
| messageService.stopRecording(); |
| } catch (IOException ioe) { |
| OseeLog.log(Activator.class, Level.WARNING, "problem when attempting to stop recording", ioe); |
| } catch (Throwable t) { |
| OseeLog.log(Activator.class, Level.SEVERE, "problem when attempting to stop recording", t); |
| } |
| } |
| }); |
| } |
| } |
| }; |
| |
| private static enum Status { |
| /** |
| * no active test manager |
| */ |
| NO_TEST_MANAGER("No test manager running"), |
| /** |
| * active test manager but not connected to a host |
| */ |
| NOT_CONNECTED("%s: Not connected to a host"), |
| /** |
| * active test manager and connected to a host |
| */ |
| CONNECTED("Connected to %s (%s)"); |
| |
| private final String txt; |
| |
| Status(final String txt) { |
| this.txt = txt; |
| } |
| |
| public String asString(Object... args) { |
| return String.format(txt, args); |
| } |
| |
| } |
| |
| private Composite parentComposite; |
| private WatchList watchList; |
| |
| private WatchViewMessageDefinitionProviderTracker watchViewMessageDefinitionProviderTracker; |
| |
| private MessageProviderVersion messageProviderVersion; |
| |
| protected boolean librariesLoaded; |
| |
| private boolean writerIsPresent; |
| |
| private ActionButton removeWritersBtn; |
| |
| public WatchView() { |
| watchFile = OseeData.getFile("msgWatch.txt"); |
| msgServiceTracker = new ClientMessageServiceTracker(Activator.getDefault().getBundle().getBundleContext(), this); |
| messageProviderVersion = new MessageProviderVersion(); |
| } |
| |
| @Override |
| public void createPartControl(Composite parent) { |
| final int numColumns = 4; |
| parentComposite = parent; |
| |
| GridLayout layout = new GridLayout(); |
| layout.numColumns = numColumns; |
| layout.verticalSpacing = 0; |
| layout.marginWidth = 5; |
| layout.marginHeight = 5; |
| parent.setLayout(layout); |
| |
| Label label = new Label(parent, SWT.RIGHT); |
| label.setText("Status:"); |
| Widgets.positionGridItem(label, false, false, SWT.END, SWT.CENTER, 1); |
| |
| statusTxt = new Label(parent, SWT.READ_ONLY); |
| statusTxt.setText(Status.NO_TEST_MANAGER.asString()); |
| Widgets.positionGridItem(statusTxt, true, false, SWT.BEGINNING, SWT.BEGINNING, 3); |
| |
| Composite buttons = new Composite(parent, SWT.NONE); |
| GridDataFactory.swtDefaults().grab(true, false).span(numColumns, 1).applyTo(buttons); |
| buttons.setLayout(new RowLayout(SWT.HORIZONTAL)); |
| |
| recordButton = new Button(buttons, SWT.TOGGLE); |
| recordButton.setText("REC"); |
| recordButton.setToolTipText("Record the messages and elements currently shown in Message Watch."); |
| recordButton.addSelectionListener(recBtnHandler); |
| recordButton.setEnabled(false); |
| |
| CsvTransform csvAction = new CsvTransform(); |
| ActionButton btn = new ActionButton(buttons, SWT.PUSH, csvAction, "Csv Transform", VIEW_ID); |
| btn.setToolTipText("Transform the base CSV format."); |
| |
| ConvertWritersToReadersAction writerAction = new ConvertWritersToReadersAction(this); |
| removeWritersBtn = new ActionButton(buttons, SWT.PUSH, writerAction, "Remove writers", VIEW_ID); |
| removeWritersBtn.setToolTipText("Converts all writers to readers"); |
| removeWritersBtn.setEnabled(false); |
| |
| final SashForm sashForm = new SashForm(parent, SWT.VERTICAL); |
| // sashForm.SASH_WIDTH = 1; |
| Widgets.positionGridItem(sashForm, true, true, SWT.FILL, SWT.FILL, numColumns); |
| |
| Composite comp = new Composite(sashForm, SWT.NONE); |
| comp.setLayout(new GridLayout(1, false)); |
| GridData gd = new GridData(GridData.FILL_BOTH); |
| comp.setLayoutData(gd); |
| |
| // Create the tree treeViewer as a child of the composite parent |
| treeViewer = |
| new MessageXViewer(comp, |
| SWT.FULL_SELECTION | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.DOUBLE_BUFFERED); |
| GridData layoutData = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH); |
| layoutData.horizontalSpan = numColumns; |
| treeViewer.getControl().setLayoutData(layoutData); |
| watchList = new WatchList(this); |
| treeViewer.setContentProvider(watchList); |
| treeViewer.setLabelProvider(new MessageWatchLabelProvider(treeViewer)); |
| treeViewer.setUseHashlookup(true); |
| |
| treeViewer.getTree().setHeaderVisible(true); |
| treeViewer.getTree().setLinesVisible(true); |
| |
| parent.addDisposeListener(new DisposeListener() { |
| |
| @Override |
| public void widgetDisposed(DisposeEvent e) { |
| saveWatchFile(); |
| } |
| }); |
| detailsBox = new DetailsBox(sashForm); |
| detailsBox.setMessageInfoSelectionListener(new MessageInfoSelectionHandler(this)); |
| |
| sashForm.setWeights(new int[] {75, 25}); |
| // Add Listeners to the Tree |
| treeViewer.addSelectionChangedListener(new ISelectionChangedListener() { |
| private AbstractTreeNode lastNodeSelected = null; |
| |
| @Override |
| public void selectionChanged(SelectionChangedEvent event) { |
| final IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection(); |
| |
| final AbstractTreeNode node = (AbstractTreeNode) selection.getFirstElement(); |
| if (node != null && node != lastNodeSelected) { |
| if (lastNodeSelected != null) { |
| lastNodeSelected.setSelected(false); |
| } |
| try { |
| selectNode(node); |
| } catch (ArrayIndexOutOfBoundsException t) { |
| // throw if there is an error in the message jar |
| // (usually... ) |
| final String msg = |
| String.format("Problems occurred when trying to display details for %s: (See Error Log)", |
| node.getName()); |
| OseeLog.log(Activator.class, Level.SEVERE, "Error while displaying details for " + node.getName(), t); |
| openInfo("Possible Message JAR Error", msg); |
| } |
| lastNodeSelected = node; |
| } |
| } |
| }); |
| treeViewer.getTree().addMouseListener(new MouseAdapter() { |
| |
| @Override |
| public void mouseDown(MouseEvent e) { |
| if (e.button == 3) { |
| showContextMenu(new Point(e.x, e.y)); |
| } |
| } |
| }); |
| |
| treeViewer.addDoubleClickListener(new IDoubleClickListener(){ |
| |
| @Override |
| public void doubleClick(DoubleClickEvent event) { |
| IStructuredSelection selection = (IStructuredSelection) event.getSelection(); |
| Object element = selection.getFirstElement(); |
| if(element instanceof ElementNode) { |
| WatchedMessageNode messageNode = getWatchList().getMessageNode(((ElementNode) element).getMessageName()); |
| IMessageSubscription subscription = messageNode.getSubscription(); |
| if(subscription.getMessageMode() == MessageMode.WRITER) { |
| ElementNode node = (ElementNode) element; |
| SetValueAction act = new SetValueAction(WatchView.this, node); |
| act.run(); |
| } |
| } |
| }}); |
| |
| // Create menu, toolbars, filters, sorters. |
| createToolBar(); |
| |
| getSite().setSelectionProvider(treeViewer); |
| |
| treeViewer.addCustomizeToViewToolbar(this); |
| createMenuActions(); |
| |
| setNoLibraryStatus(); |
| IOteClientService clientService = Activator.getDefault().getOteClientService(); |
| if (clientService == null) { |
| throw new IllegalStateException("cannot acquire ote client service"); |
| } |
| msgServiceTracker.open(true); |
| |
| cb = new Clipboard(Display.getCurrent()); |
| |
| treeViewer.getControl().addKeyListener(new KeyListener() { |
| |
| @Override |
| public void keyPressed(KeyEvent e) { |
| if (e.stateMask == SWT.CTRL && e.keyCode == 'v') { |
| TextTransfer transfer = TextTransfer.getInstance(); |
| String data = (String) cb.getContents(transfer); |
| if (data != null) { |
| AddWatchParameter param = new AddWatchParameter(); |
| addWatchMessage(param); |
| } |
| } else if (e.stateMask != SWT.CTRL && e.stateMask != SWT.ALT && e.keyCode == SWT.DEL){ |
| final IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection(); |
| watchList.deleteSelection(selection); |
| refresh(); |
| } |
| } |
| |
| @Override |
| public void keyReleased(KeyEvent e) { |
| } |
| }); |
| |
| addSelectionBackgroundChanger(treeViewer); |
| |
| int ops = DND.DROP_COPY | DND.DROP_MOVE; |
| Transfer[] transfers = new Transfer[] {FileTransfer.getInstance(), TextTransfer.getInstance()}; |
| treeViewer.addDropSupport(ops, transfers, new WatchViewDropAdapter(this)); |
| |
| watchViewMessageDefinitionProviderTracker = new WatchViewMessageDefinitionProviderTracker(FrameworkUtil.getBundle(getClass()).getBundleContext(), this); |
| watchViewMessageDefinitionProviderTracker.open(true); |
| |
| clientService.addConnectionListener(this); |
| loadWatchFile(); |
| |
| } |
| |
| /** |
| * This code ensures that the Writer only background color is preserved when the row is selected. |
| * Otherwise, the selection would hide whether the message is a reader or a writer. |
| * @param viewer |
| */ |
| private void addSelectionBackgroundChanger(final MessageXViewer viewer) { |
| viewer.getTree().addListener(SWT.EraseItem, new Listener() { |
| |
| @Override |
| public void handleEvent(Event event) { |
| |
| Tree table =(Tree)event.widget; |
| TreeItem item =(TreeItem)event.item; |
| Object data = item.getData(); |
| if( data instanceof WatchedMessageNode ) { |
| WatchedMessageNode watchedMessageNode = (WatchedMessageNode) data; |
| if( watchedMessageNode.getSubscription().getMessageMode() == MessageMode.READER){ |
| return; |
| } |
| |
| } else { |
| return; |
| } |
| event.detail &= ~SWT.HOT; |
| |
| if ((event.detail & SWT.SELECTED) == 0) return; /// item not selected |
| |
| int clientWidth = table.getClientArea().width; |
| |
| GC gc = event.gc; |
| Color oldForeground = gc.getForeground(); |
| Color oldBackground = SWTResourceManager.getColor(202,225,255); |
| |
| final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); |
| final AbstractTreeNode node = findElementMatching(selection, data); |
| Color background = node.getBackground(); |
| if( background == null ) |
| background = oldBackground; |
| |
| gc.setBackground(background); |
| gc.setForeground(oldForeground); |
| gc.fillRectangle(0, event.y, clientWidth, event.height); |
| |
| gc.setForeground(oldForeground); |
| gc.setBackground(oldBackground); |
| event.detail &= ~SWT.SELECTED; |
| } |
| |
| private AbstractTreeNode findElementMatching(IStructuredSelection selection, Object data) { |
| Object[] array = selection.toArray(); |
| for (int i = 0; i < array.length; i++) { |
| Object cur = array[i]; |
| if( cur == data) { |
| return (AbstractTreeNode) cur; |
| } |
| } |
| return (AbstractTreeNode) data; |
| } |
| }); |
| } |
| |
| @Override |
| public void dispose() { |
| watchViewMessageDefinitionProviderTracker.close(); |
| if (detailsBox != null) { |
| detailsBox.dispose(); |
| } |
| msgServiceTracker.close(); |
| Activator.getDefault().getOteClientService().removeConnectionListener(WatchView.this); |
| SWTResourceManager.dispose(); |
| super.dispose(); |
| } |
| |
| public void createToolBar() { |
| Action expandAction = new Action("Expand All") { |
| |
| @Override |
| public void run() { |
| treeViewer.getTree().setRedraw(false); |
| treeViewer.expandAll(); |
| treeViewer.getTree().setRedraw(true); |
| } |
| }; |
| expandAction.setImageDescriptor(WatchImages.EXPAND_STATE.createImageDescriptor()); |
| expandAction.setToolTipText("Expand All"); |
| |
| Action showNameAction = new Action("Show Names", SWT.TOGGLE) { |
| |
| @Override |
| public void run() { |
| treeViewer.refresh(); |
| } |
| }; |
| showNameAction.setImageDescriptor(WatchImages.SHOW_NAMES.createImageDescriptor()); |
| showNameAction.setToolTipText("Show Message Names"); |
| |
| Action collapseAction = new Action("Collapse All") { |
| |
| @Override |
| public void run() { |
| treeViewer.getTree().setRedraw(false); |
| treeViewer.collapseAll(); |
| treeViewer.getTree().setRedraw(true); |
| } |
| }; |
| collapseAction.setImageDescriptor(WatchImages.COLLAPSE_STATE.createImageDescriptor()); |
| collapseAction.setToolTipText("Collapse All"); |
| |
| Action deleteAction = new Action("Delete") { |
| @Override |
| public void run() { |
| final IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection(); |
| watchList.deleteSelection(selection); |
| refresh(); |
| } |
| }; |
| |
| deleteAction.setToolTipText("Delete"); |
| |
| deleteAction.setImageDescriptor(WatchImages.DELETE.createImageDescriptor()); |
| |
| Action deleteAllAction = new Action("Delete All") { |
| |
| @Override |
| public void run() { |
| if (MessageDialog.openConfirm(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), |
| "Delete All", "Delete All Watch Items?")) { |
| watchList.deleteAll(); |
| refresh(); |
| } |
| } |
| }; |
| deleteAllAction.setToolTipText("Delete All"); |
| deleteAllAction.setImageDescriptor(WatchImages.DELETE_ALL.createImageDescriptor()); |
| |
| Action refreshAction = new Action("Refresh") { |
| @Override |
| public void run() { |
| treeViewer.refresh(); |
| } |
| }; |
| refreshAction.setToolTipText("refresh"); |
| refreshAction.setImageDescriptor(WatchImages.REFRESH.createImageDescriptor()); |
| |
| Action saveAction = new Action("Save Items") { |
| private String saveFilePath = null; |
| private String lastSaveFileName = null; |
| |
| @Override |
| public void run() { |
| final FileDialog dialog = new FileDialog(treeViewer.getTree().getShell(), SWT.SAVE); |
| dialog.setFilterExtensions(new String[] {"*.mwi"}); |
| if (saveFilePath == null) { |
| saveFilePath = System.getProperty("user.home"); |
| if(saveFilePath == null) { |
| saveFilePath = OseeData.getPath().toOSString(); |
| } |
| } |
| if (lastSaveFileName == null) { |
| lastSaveFileName = "msgWatchItems.mwi"; |
| } |
| dialog.setFilterPath(saveFilePath); |
| dialog.setFileName(lastSaveFileName); |
| |
| String selectedFile = dialog.open(); |
| if (selectedFile != null) { |
| if (!selectedFile.endsWith(".mwi")) { |
| selectedFile += ".mwi"; |
| } |
| final File saveFile = new File(selectedFile); |
| saveFilePath = saveFile.getAbsolutePath(); |
| lastSaveFileName = saveFile.getName(); |
| saveWatchFile(saveFile); |
| } |
| } |
| }; |
| saveAction.setToolTipText("Save Watch Items"); |
| saveAction.setImageDescriptor(WatchImages.SAVE.createImageDescriptor()); |
| |
| Action loadAction = new Action("Load Items") { |
| private String loadFilePath = null; |
| private String lastLoadFileName = null; |
| |
| @Override |
| public void run() { |
| final FileDialog dialog = new FileDialog(treeViewer.getTree().getShell(), SWT.OPEN); |
| dialog.setFilterExtensions(new String[] {"*.mwi"}); |
| if (loadFilePath == null) { |
| loadFilePath = OseeData.getPath().toOSString(); |
| } |
| if (lastLoadFileName != null) { |
| dialog.setFileName(lastLoadFileName); |
| } |
| |
| dialog.setFilterPath(loadFilePath); |
| |
| String selectedFile = dialog.open(); |
| if (selectedFile != null) { |
| if (!selectedFile.endsWith(".mwi")) { |
| selectedFile += ".mwi"; |
| } |
| final File loadFile = new File(selectedFile); |
| loadFilePath = loadFile.getAbsolutePath(); |
| lastLoadFileName = loadFile.getName(); |
| loadWatchFile(loadFile); |
| } |
| } |
| }; |
| loadAction.setToolTipText("Load Watch Items"); |
| loadAction.setImageDescriptor(WatchImages.OPEN.createImageDescriptor()); |
| IToolBarManager toolbarManager = getViewSite().getActionBars().getToolBarManager(); |
| toolbarManager.add(showNameAction); |
| toolbarManager.add(refreshAction); |
| toolbarManager.add(expandAction); |
| toolbarManager.add(collapseAction); |
| toolbarManager.add(deleteAction); |
| toolbarManager.add(deleteAllAction); |
| toolbarManager.add(saveAction); |
| toolbarManager.add(loadAction); |
| } |
| |
| @Override |
| public void setFocus() { |
| // Set focus so that context sensitive help will work as soon as this |
| // view is selected. |
| parentComposite.setFocus(); |
| } |
| |
| /** |
| * display details about specified node |
| * |
| * @param node node whose details will be displayed in the detail window of the GUI |
| */ |
| public void setDetailText(final AbstractTreeNode node) { |
| detailsBox.setDetailText(node); |
| } |
| |
| public void selectNode(AbstractTreeNode node) { |
| node.setSelected(true); |
| detailsBox.selectNode(node); |
| } |
| |
| /** |
| * shows a context menu depending on the point |
| */ |
| void showContextMenu(Point p) { |
| final Tree tree = treeViewer.getTree(); |
| final Menu contextMenu = getPopupMenu(tree.getParent()); |
| if (contextMenu != null) { |
| p = tree.toDisplay(p); |
| contextMenu.setLocation(p); |
| contextMenu.setVisible(true); |
| } |
| } |
| |
| public void addWatchMessage(final AddWatchParameter parameter) { |
| new Thread(new Runnable(){ |
| @Override |
| public void run() { |
| for (MessageParameter message : parameter.getMessageParameters()) { |
| Collection<ElementPath> elements = parameter.getMessageElements(message.getMessageName()); |
| OseeLog.logf(Activator.class, Level.FINEST, "Watch request for message %s", message); |
| try { |
| if (elements == null) { |
| elements = new ArrayList<ElementPath>(); |
| } |
| MessageMode mode = message.isWriter() ? MessageMode.WRITER : MessageMode.READER; |
| watchList.createElements(message.getMessageName(),message.getDataType(), mode, elements, message.getValueMap()); |
| } catch (ClassNotFoundException ex1) { |
| if (openProceedWithProcessing("Could not find a class definition for " + message + "\n Do you wish to continue")) { |
| continue; |
| } else { |
| return; |
| } |
| } catch (InstantiationException ex1) { |
| if (openProceedWithProcessing("failed to instantiate " + message + "\n Do you wish to continue")) { |
| continue; |
| } else { |
| return; |
| } |
| } catch (Exception ex1) { |
| OseeLog.log(Activator.class, Level.SEVERE, "failed to create message node", ex1); |
| if (openProceedWithProcessing("Error processing " + message + ". See Error Log for details.\n Do you wish to continue")) { |
| continue; |
| } else { |
| return; |
| } |
| } |
| } |
| |
| Display.getDefault().asyncExec(new Runnable(){ |
| @Override |
| public void run() { |
| refresh(); |
| } |
| }); |
| } |
| }).start(); |
| } |
| |
| public void refresh() { |
| treeViewer.refresh(); |
| saveWatchFile(); |
| } |
| |
| /** |
| * Convienence method. Opens an info dialog |
| */ |
| private void openInfo(final String title, final String message) { |
| MessageDialog.openInformation(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), title, message); |
| } |
| |
| private boolean openProceedWithProcessing(final String message) { |
| MessageDialog dialog = |
| new MessageDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Proceed?", null, message, |
| MessageDialog.QUESTION, new String[] {"Continue processing with next message", "End message processing"}, 0); |
| return dialog.open() == Window.OK; |
| } |
| |
| private void onDisconnected() { |
| OseeLog.log(Activator.class, Level.INFO, "Entered onDisconnected()"); |
| if (!recordButton.isDisposed()) { |
| recordButton.setSelection(false); |
| } |
| try { |
| if (Benchmark.isBenchmarkingEnabled()) { |
| OseeLog.logf(Activator.class, Level.INFO, "%s: # samples=%d, max=%d, min=%d, avg=%d", benchMark.getName(), |
| benchMark.getTotalSamples(), benchMark.getLongestSample(), benchMark.getShortestSample(), |
| benchMark.getAverage()); |
| } |
| } catch (Throwable t) { |
| OseeLog.log(Activator.class, Level.WARNING, "Exception during disconnect", t); |
| } |
| |
| } |
| |
| private Menu getPopupMenu(final Composite composite) { |
| Menu menu = treeViewer.getMenuManager().createContextMenu(composite); |
| return menu; |
| } |
| |
| public void loadWatchFile() { |
| loadWatchFile(watchFile); |
| } |
| |
| public void loadWatchFile(final File watchFile) { |
| if (watchFile != null && watchFile.exists()) { |
| final Job job = new LoadWatchListJob(this, watchFile); |
| Jobs.startJob(job); |
| } |
| } |
| |
| public void loadWatchFile(final String watchFileText) { |
| final Job job = new LoadWatchListJob(this, new File(watchFileText)); |
| Jobs.startJob(job); |
| } |
| |
| public void saveWatchFile() { |
| saveWatchFile(watchFile); |
| } |
| |
| public void saveWatchFile(File watchFile) { |
| if (watchFile == null) { |
| return; |
| } |
| try { |
| final FileWriter fw = new FileWriter(watchFile); |
| fw.write("version=3.0\n"); |
| ArrayList<ElementNode> descendants = new ArrayList<ElementNode>(256); |
| for (MessageNode treeItem : watchList.getMessages()) { |
| WatchedMessageNode msg = (WatchedMessageNode) treeItem; |
| fw.write("msg:"); |
| fw.write(msg.getMessageClassName()); |
| fw.write('\n'); |
| fw.write("isWriter="); |
| boolean isWriter = msg.getSubscription().getMessageMode() == MessageMode.WRITER; |
| fw.write(Boolean.toString(isWriter)); |
| fw.write('\n'); |
| |
| fw.write("data type="); |
| fw.write(msg.getSubscription().getMemType().name()); |
| fw.write('\n'); |
| |
| descendants.clear(); |
| msg.collectDescendants(descendants); |
| Map<ElementPath, String> map = msg.getRequestedValueMap(); |
| |
| boolean writeElement = isWriter; |
| for (ElementNode el : descendants) { |
| fw.write('@'); |
| fw.write(el.getElementPath().asString()); |
| if (writeElement) { |
| String value; |
| // if a map is present then that means we have a requested value but the message |
| // subscription is not active. We want to use the requested value |
| if (map != null) { |
| value = map.get(el.getElementPath()); |
| } else { |
| // upon activation of a subscription the map will be cleared so |
| // use the node's value |
| value = ((WatchedElementNode) el).getValue(); |
| } |
| if (value != null) { |
| fw.write('='); |
| fw.write(value); |
| } |
| } |
| fw.write('\n'); |
| } |
| msg.getRecordingState().write(fw); |
| } |
| fw.close(); |
| } catch (Exception e) { |
| OseeLog.log(Activator.class, Level.SEVERE, "failed to write watch file at " + watchFile.getAbsolutePath(), e); |
| } |
| } |
| |
| public TreeViewer getTreeViewer() { |
| return treeViewer; |
| } |
| |
| public void updateMenuActions(final IMenuManager mm) { |
| |
| final IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection(); |
| if (selection.size() > 0) { |
| final AbstractTreeNode node = (AbstractTreeNode) selection.getFirstElement(); |
| node.visit(new INodeVisitor<Object>() { |
| |
| @Override |
| public Object elementNode(ElementNode node) { |
| if (selection.size() == 1) { |
| mm.insertBefore(XViewer.MENU_GROUP_PRE, new SetValueAction(WatchView.this, node)); |
| mm.insertBefore(XViewer.MENU_GROUP_PRE, new ZeroizeElementAction(node)); |
| } |
| return null; |
| } |
| |
| @Override |
| public Object messageNode(MessageNode node) { |
| if (selection.size() == 1) { |
| WatchedMessageNode msgNode = (WatchedMessageNode) node; |
| mm.insertBefore(XViewer.MENU_GROUP_PRE, new WatchElementAction(WatchView.this, (WatchedMessageNode) node)); |
| mm.insertBefore(XViewer.MENU_GROUP_PRE, new Separator()); |
| mm.insertBefore(XViewer.MENU_GROUP_PRE, SetDataSourceMenu.createMenu(msgNode)); |
| mm.insertBefore(XViewer.MENU_GROUP_PRE, SetMessageModeMenu.createMenu(WatchView.this, msgNode)); |
| mm.insertBefore(XViewer.MENU_GROUP_PRE, new SendMessageAction(msgNode)); |
| mm.insertBefore(XViewer.MENU_GROUP_PRE, new ZeroizeMessageAction(msgNode)); |
| } |
| return null; |
| } |
| |
| @Override |
| public Object rootNode(RootNode node) { |
| return null; |
| } |
| |
| }); |
| mm.insertBefore(XViewer.MENU_GROUP_PRE, new ClearUpdatesAction(watchList, selection)); |
| mm.insertBefore(XViewer.MENU_GROUP_PRE, new DeleteSelectionAction(watchList, selection)); |
| } |
| mm.insertBefore(XViewer.MENU_GROUP_PRE, new Separator()); |
| } |
| |
| public void createMenuActions() { |
| MenuManager mm = treeViewer.getMenuManager(); |
| mm.createContextMenu(treeViewer.getControl()); |
| mm.addMenuListener(new IMenuListener() { |
| @Override |
| public void menuAboutToShow(IMenuManager manager) { |
| updateMenuActions(manager); |
| } |
| }); |
| |
| } |
| |
| @Override |
| public void onPostConnect(final ConnectionEvent event) { |
| OseeLog.log(Activator.class, Level.INFO, "Entered onConnectionEstablished()"); |
| |
| if (event.getEnvironment() instanceof ITestEnvironmentMessageSystem) { |
| Displays.pendInDisplayThread(new Runnable() { |
| @Override |
| public void run() { |
| recordButton.setEnabled(true); |
| } |
| }); |
| } |
| } |
| |
| @Override |
| public void onPreDisconnect(ConnectionEvent event) { |
| Displays.ensureInDisplayThread(new Runnable() { |
| @Override |
| public void run() { |
| recordButton.setEnabled(false); |
| onDisconnected(); |
| } |
| }); |
| } |
| |
| private void setNoLibraryStatus() { |
| if(!treeViewer.getTree().isDisposed()){ |
| treeViewer.getTree().setToolTipText(""); |
| } |
| if(!statusTxt.isDisposed()){ |
| statusTxt.setText("no library detected"); |
| } |
| } |
| |
| @Override |
| public void onConnectionLost(IServiceConnector connector) { |
| } |
| |
| @Override |
| public void oteMessageServiceAcquired(final IOteMessageService service) { |
| Displays.pendInDisplayThread(new Runnable() { |
| @Override |
| public void run() { |
| messageService = service; |
| recordButton.setEnabled(true); |
| treeViewer.setInput(service); |
| } |
| }); |
| } |
| |
| @Override |
| public void oteMessageServiceReleased() { |
| Displays.pendInDisplayThread(new Runnable() { |
| @Override |
| public void run() { |
| if (!recordButton.isDisposed()) { |
| recordButton.setEnabled(false); |
| } |
| if (!treeViewer.getControl().isDisposed()) { |
| treeViewer.setInput(null); |
| } |
| messageService = null; |
| } |
| }); |
| } |
| |
| |
| |
| public void addMessageDefinitionProvider(MessageDefinitionProvider provider) { |
| messageProviderVersion.add(provider); |
| Displays.ensureInDisplayThread(new Runnable() { |
| @Override |
| public void run() { |
| try { |
| librariesLoaded = true; |
| updateStatusLabel(); |
| statusTxt.setToolTipText(messageProviderVersion.getVersion()); |
| } catch (Exception ex) { |
| OseeLog.log(Activator.class, Level.SEVERE, "exception while processing library", ex); |
| } |
| } |
| }); |
| } |
| |
| public void removeMessageDefinitionProvider(MessageDefinitionProvider provider) { |
| messageProviderVersion.remove(provider); |
| Displays.ensureInDisplayThread(new Runnable() { |
| @Override |
| public void run() { |
| if(messageProviderVersion.isAnyAvailable()){ |
| if(!statusTxt.isDisposed()){ |
| librariesLoaded = true; |
| updateStatusLabel(); |
| statusTxt.setToolTipText(messageProviderVersion.getVersion()); |
| } |
| } else { |
| setNoLibraryStatus(); |
| } |
| } |
| }); |
| } |
| |
| private void updateStatusLabel() { |
| String text = ""; |
| if( librariesLoaded) { |
| text = "libraries loaded"; |
| } else { |
| text = Status.NO_TEST_MANAGER.asString(); |
| } |
| |
| if(writerIsPresent) { |
| text += ", WRITERS ARE PRESENT"; |
| statusTxt.setBackground(SWTResourceManager.getColor(COLOR_GOLDENROD)); |
| } else { |
| text += ", no writers present"; |
| statusTxt.setBackground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND)); |
| } |
| |
| statusTxt.setText(text); |
| statusTxt.getParent().layout(); |
| } |
| |
| public WatchList getWatchList() { |
| return watchList; |
| } |
| |
| public void setWriterPresent(boolean writerIsPresent) { |
| if( this.writerIsPresent != writerIsPresent ) { |
| this.writerIsPresent = writerIsPresent; |
| updateStatusLabel(); |
| updateWriterButton(); |
| } |
| } |
| |
| private void updateWriterButton() { |
| removeWritersBtn.setEnabled(writerIsPresent); |
| } |
| |
| } |