blob: 04d78abb8e11605302b720358f2d62dab4e99baa [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2016 Ericsson and others.
* 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:
* Ericsson - Initial API and implementation
* Dmitry Kozlov (Mentor Graphics) - Trace control view enhancements (Bug 390827)
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints;
import java.text.DateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceStatusDMData2;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.STOP_REASON_ENUM;
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.jface.action.Action;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
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.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Slider;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.UIJob;
/**
* TraceControlView Part
*
* This view is used to control Tracing.
*
* @since 2.1
*/
public class TraceControlView extends ViewPart implements IViewPart {
private static final int ACTION_BUTTON_INDENTATION = 10;
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
protected static final int UI_REFRESH_DELAY = 1000; // milliseconds
public static class FailedTraceVariableCreationException extends Exception {
private static final long serialVersionUID = -3042693455630687285L;
FailedTraceVariableCreationException() {}
FailedTraceVariableCreationException(String errorMessage) {
super(errorMessage);
}
}
/**
* Action to refresh the content of the view.
*/
private final class RefreshViewAction extends Action {
public RefreshViewAction() {
setText(TracepointsMessages.TraceControlView_action_Refresh_label);
setImageDescriptor(TracepointImageRegistry.getImageDescriptor(TracepointImageRegistry.ICON_Refresh_enabled));
setDisabledImageDescriptor(TracepointImageRegistry.getImageDescriptor(TracepointImageRegistry.ICON_Refresh_disabled));
}
@Override
public void run() {
fLastRefreshTime = System.currentTimeMillis();
fTraceControlModel.updateContent();
}
}
/**
* Action to automatically refresh the content of the view by polling trace-status.
*/
protected final class AutoRefreshAction extends Action {
public AutoRefreshAction() {
super(TracepointsMessages.TraceControlView_auto_refresh_action_label, AS_CHECK_BOX);
setImageDescriptor(TracepointImageRegistry.getImageDescriptor(TracepointImageRegistry.ICON_Refresh_Auto));
}
@Override
public void run() {
if (isChecked()) {
// Call to updateContent which starts refreshUI job only if necessary
// (when tracing is running)
fAutoRefreshEnabled = true;
fRefreshViewAction.setEnabled(false);
fTraceControlModel.updateContent();
} else {
fAutoRefreshEnabled = false;
fRefreshViewAction.setEnabled(true);
}
}
}
/**
* Action to refresh the content of the view.
*/
protected final class DisconnectedTracingAction extends Action {
public DisconnectedTracingAction() {
super(TracepointsMessages.TraceControlView_action_Disconnected_tracing_label, AS_CHECK_BOX);
setImageDescriptor(TracepointImageRegistry.getImageDescriptor(TracepointImageRegistry.ICON_Disconnected_Tracing));
}
@Override
public void run() {
fTraceControlModel.setDisconnectedTracing(isChecked());
}
}
protected final class OpenTraceVarDetailsAction extends Action {
public OpenTraceVarDetailsAction() {
setText(TracepointsMessages.TraceControlView_action_trace_variable_details);
setImageDescriptor(TracepointImageRegistry.getImageDescriptor(TracepointImageRegistry.ICON_Trace_Variables));
}
@Override
public void run() {
Shell shell = Display.getDefault().getActiveShell();
TraceVarDetailsDialog dialog = new TraceVarDetailsDialog(shell, TraceControlView.this);
dialog.open();
}
}
protected final class ExitVisualizationModeDetailsAction extends Action {
public ExitVisualizationModeDetailsAction() {
setText(TracepointsMessages.TraceControlView_action_exit_visualization_mode);
setImageDescriptor(TracepointImageRegistry.getImageDescriptor(TracepointImageRegistry.ICON_Exit_Visualization));
}
@Override
public void run() {
fTraceControlModel.exitVisualizationMode();
// Content of view will be updated from the event
// triggered by this asynchronous operation.
}
}
protected TraceControlModel fTraceControlModel;
protected RefreshViewAction fRefreshViewAction;
protected boolean fAutoRefreshEnabled;
protected DisconnectedTracingAction fDisconnectedTracingAction;
protected OpenTraceVarDetailsAction fOpenTraceVarDetails;
protected ExitVisualizationModeDetailsAction fExitVisualizationAction;
protected AutoRefreshAction fAutoRefreshAction;
protected boolean fTraceVisualization;
protected Job refreshUIJob;
protected Font cachedBold;
protected long fLastRefreshTime;
protected ITraceStatusDMData2 fLastTraceData;
protected Composite fTopComposite;
protected Composite fStatusComposite;
protected Label fStatusLabel;
protected Label fSecondaryStatusLabel;
protected Composite fSecondaryStatusComposite;
protected FlatButton fActionButton;
protected Composite fBufferComposite;
protected Label fBufferCollectedFramesLabel;
protected FlatRadioButton fSetCircularBufferButton;
protected CircularProgress fBufferProgress;
protected Composite fFrameComposite;
protected Label fFrameLabel;
protected Label fFrameNumberLabel;
protected Slider fFrameSlider;
protected Composite fNotesComposite;
protected Label fNotesContentLabel;
protected Text fNotesContentText;
protected Button fSetNotesButton;
public TraceControlView() {
}
@Override
public void init(IViewSite site) throws PartInitException {
super.init(site);
fTraceControlModel = new TraceControlModel(this);
}
@Override
public void init(IViewSite site, IMemento memento) throws PartInitException {
init(site);
}
@Override
public void createPartControl(Composite parent) {
createActions();
fTopComposite = new Composite(parent, SWT.NONE);
GridLayout topLayout = new GridLayout(1, false);
topLayout.marginWidth = 0;
topLayout.marginHeight = 0;
fTopComposite.setLayout(topLayout);
fTopComposite.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WHITE));
// Tracing status line
createStatusLine(fTopComposite);
// Secondary status: start time, stop time and reason
setSecondaryStatusLineVisible(false, null);
// Buffer line
createBufferLine(fTopComposite);
setBufferLineVisible(false, null, false);
// Frame line
createFrameLine(fTopComposite);
setFrameLineVisible(false, null);
// Trace notes
//createNotesLine(fTopComposite);
//setNotesLineVisible(false, null, false);
fTraceControlModel.init();
}
protected void createStatusLine(Composite parent) {
fStatusComposite = new Composite(parent, SWT.NONE);
GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
gd.horizontalSpan = 2;
gd.minimumHeight = 22;
fStatusComposite.setLayoutData(gd);
GridLayout l = new GridLayout(2,false);
l.marginBottom = 0;
fStatusComposite.setLayout(l);
fStatusComposite.setBackgroundMode(SWT.INHERIT_FORCE);
fStatusLabel = new Label(fStatusComposite, SWT.NONE);
if (cachedBold == null) {
FontData fontData = fStatusLabel.getFont().getFontData()[0];
fontData.setStyle(SWT.BOLD);
cachedBold = new Font(fStatusLabel.getDisplay(),fontData);
}
fStatusLabel.setFont(cachedBold);
GridData d = new GridData(SWT.LEFT, SWT.CENTER, false, false);
fStatusLabel.setLayoutData(d);
fStatusLabel.setText(TracepointsMessages.TraceControlView_trace_status_no_debug_session);
fStatusLabel.setBackground(parent.getBackground());
fActionButton = new FlatButton(fStatusComposite, SWT.NONE);
fActionButton.setText(EMPTY_STRING);
GridData acGd = new GridData(SWT.LEFT, SWT.CENTER, false, false);
acGd.horizontalIndent = ACTION_BUTTON_INDENTATION;
fActionButton.setLayoutData(acGd);
fActionButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
// Run action
IHandlerService handlerService = getSite().getService(IHandlerService.class);
if (handlerService == null) {
GdbUIPlugin.log(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, "Missing command handler service")); //$NON-NLS-1$
return;
}
try {
String text = ((FlatButton)e.getSource()).getText();
if (TracepointsMessages.TraceControlView_action_start.equals(text) ||
TracepointsMessages.TraceControlView_action_restart.equals(text)) {
handlerService.executeCommand("org.eclipse.cdt.debug.ui.command.startTracing", null); //$NON-NLS-1$
} else if (TracepointsMessages.TraceControlView_action_stop.equals(text)) {
handlerService.executeCommand("org.eclipse.cdt.debug.ui.command.stopTracing", null); //$NON-NLS-1$
} else if (TracepointsMessages.TraceControlView_action_finish_visualization.equals(text)) {
fTraceControlModel.exitVisualizationMode();
}
// Note that the content of the view will be updated due to the event
// triggered by the above operations. There is no point in updating the
// content ourselves since some of the above calls are asynchronous
// and have not completed yet.
} catch (Exception ex) {
GdbUIPlugin.log(ex);
}
}
});
fSecondaryStatusLabel = new Label(fStatusComposite, SWT.NONE | SWT.WRAP);
GridData sslGd = new GridData(SWT.FILL, SWT.TOP, true, false);
sslGd.horizontalSpan = 2;
fSecondaryStatusLabel.setLayoutData(sslGd);
fSecondaryStatusLabel.setBackground(parent.getBackground());
Label separator = new Label(fStatusComposite, SWT.SEPARATOR | SWT.HORIZONTAL);
GridData sGd = new GridData(SWT.FILL, SWT.BOTTOM, true, false);
//sGd.heightHint = 3;
sGd.horizontalSpan = 2;
separator.setLayoutData(sGd);
}
protected void setActionLinkVisible(boolean visible, String text) {
fActionButton.setVisible(visible);
fActionButton.setText(visible ? text: EMPTY_STRING);
}
private void setSecondaryStatusLineVisible(boolean visible, ITraceStatusDMData2 tData) {
fSecondaryStatusLabel.setVisible(visible);
((GridData)fSecondaryStatusLabel.getLayoutData()).exclude = !visible;
if (visible && tData != null) {
STOP_REASON_ENUM stopReason = tData.getStopReason();
if (stopReason != null) {
fSecondaryStatusLabel.setText(getStopMessage(tData));
} else if (tData.isTracingActive() && tData.getStartTime() != null) {
String user = EMPTY_STRING;
String lastRefreshed = EMPTY_STRING;
// In case autorefresh is disabled, show when view was manually refreshed last time
if (!fAutoRefreshEnabled) {
lastRefreshed = TracepointsMessages.bind(
TracepointsMessages.TraceControlView_trace_status_secondary_refresh_time,
formatTimeInterval(fLastRefreshTime, System.currentTimeMillis(), true));
}
if (tData.getUserName() != null && tData.getUserName().length() > 0) {
user = TracepointsMessages.bind(TracepointsMessages.TraceControlView_trace_status_secondary_user, tData.getUserName());
}
fSecondaryStatusLabel.setText(TracepointsMessages.bind(
TracepointsMessages.TraceControlView_trace_status_secondary_running,
new Object[] {
formatTime(tData.getStartTime()),
user,
lastRefreshed}
));
} else {
// Should not happen if usage is correct
fSecondaryStatusLabel.setText(EMPTY_STRING);
}
} else {
fSecondaryStatusLabel.setText(EMPTY_STRING);
}
}
protected void createNotesLine(final Composite parent) {
// Trace notes: notes text and edit notes button
fNotesComposite = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(3, false);
layout.marginWidth = 0;
layout.marginHeight = 0;
fNotesComposite.setLayout(layout);
fNotesComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
fNotesComposite.setBackgroundMode(SWT.INHERIT_FORCE);
// Separator on the left of whole notes composite
Label separator = new Label(fNotesComposite, SWT.SEPARATOR | SWT.VERTICAL);
GridData slGd = new GridData(SWT.RIGHT, SWT.FILL, false, true);
//slGd.widthHint = 3;
slGd.verticalSpan = 4;
separator.setLayoutData(slGd);
separator.setBackground(fNotesComposite.getBackground());
Label fNotesLabel = new Label(fNotesComposite, SWT.NONE);
fNotesLabel.setBackground(parent.getBackground());
fNotesLabel.setText(TracepointsMessages.TraceControlView_trace_notes_label);
if (cachedBold != null) {
fNotesLabel.setFont(cachedBold);
}
fSetNotesButton = new Button(fNotesComposite, SWT.TOGGLE);
fSetNotesButton.setImage(TracepointImageRegistry.getImageDescriptor(
TracepointImageRegistry.ICON_Edit_enabled).createImage());
fSetNotesButton.setSelection(false);
fSetNotesButton.setToolTipText(TracepointsMessages.TraceControlView_trace_notes_edit_tooltip);
fSetNotesButton.setLayoutData(new GridData(SWT.END, SWT.TOP, false, false));
fSetNotesButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
handleEditNotesButtonPressed();
}
});
fNotesContentLabel = new Label(fNotesComposite, SWT.WRAP);
fNotesContentLabel.setBackground(parent.getBackground());
fNotesContentLabel.setText(TracepointsMessages.TraceControlView_trace_notes_not_set);
GridData nclGd = new GridData(SWT.FILL, SWT.TOP, true, false);
nclGd.horizontalSpan = 2;
fNotesContentLabel.setLayoutData(nclGd);
fNotesContentText = new Text(fNotesComposite, SWT.BORDER);
fNotesContentText.setVisible(false);
GridData gd = new GridData(SWT.FILL, SWT.TOP, true, false);
gd.horizontalSpan = 2;
gd.exclude = true;
fNotesContentText.setLayoutData(gd);
fNotesContentText.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {
fSetNotesButton.setSelection(false);
handleEditNotesButtonPressed();
}
});
fNotesContentText.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.keyCode == 0x1b) {
// Esc was pressed, cancel editing
fSetNotesButton.setSelection(false);
handleEditNotesButtonPressed(true);
}
}
});
}
protected void handleEditNotesButtonPressed() {
handleEditNotesButtonPressed(false);
}
protected void handleEditNotesButtonPressed(boolean cancelEditing) {
boolean isEditMode = fSetNotesButton.getSelection();
fNotesContentLabel.setVisible(!isEditMode);
((GridData)fNotesContentLabel.getLayoutData()).exclude = isEditMode;
fNotesContentText.setVisible(isEditMode);
((GridData)fNotesContentText.getLayoutData()).exclude = !isEditMode;
fNotesContentText.setFocus();
if (isEditMode) {
String txt = fNotesContentLabel.getText();
txt = TracepointsMessages.TraceControlView_trace_notes_not_set.equals(txt) ? EMPTY_STRING : txt;
fNotesContentText.setText(txt);
fSetNotesButton.setToolTipText(TracepointsMessages.TraceControlView_trace_notes_save_tooltip);
} else {
fSetNotesButton.setToolTipText(TracepointsMessages.TraceControlView_trace_notes_edit_tooltip);
if (!cancelEditing) {
fNotesContentLabel.setText(fNotesContentText.getText());
fNotesContentLabel.getSize();
fTraceControlModel.setTraceNotes(fNotesContentText.getText());
}
}
fNotesComposite.layout();
fNotesComposite.redraw();
fTraceControlModel.updateContent();
}
protected void setNotesLineVisible(boolean visible, ITraceStatusDMData2 tData, boolean readonly) {
fNotesComposite.setVisible(visible);
((GridData)fNotesComposite.getLayoutData()).exclude = !visible;
if (visible) {
if (tData.getNotes() != null && tData.getNotes().length() > 0) {
fNotesContentLabel.setText(removeQuotes(tData.getNotes()));
} else {
fNotesContentLabel.setText(TracepointsMessages.TraceControlView_trace_notes_not_set);
}
if (tData != null && tData.getStartTime() != null)
fSetNotesButton.setEnabled(!readonly);
}
}
protected void createFrameLine(Composite parent) {
fFrameComposite = new Composite(parent, SWT.NONE);
GridData fcGd = new GridData(SWT.FILL, SWT.TOP, true, false);
fcGd.horizontalSpan = 2;
fFrameComposite.setLayoutData(fcGd);
GridLayout layout = new GridLayout(2, false);
layout.marginHeight = 0;
fFrameComposite.setLayout(layout);
Label separator = new Label(fFrameComposite, SWT.SEPARATOR | SWT.HORIZONTAL);
GridData sepGd = new GridData(SWT.FILL, SWT.CENTER, true, false);
sepGd.horizontalSpan = 2;
sepGd.verticalIndent = 2;
separator.setLayoutData(sepGd);
fFrameSlider = new Slider(fFrameComposite, SWT.HORIZONTAL | SWT.BORDER);
GridData gd2 = new GridData(SWT.FILL, SWT.CENTER, true, false);
gd2.horizontalSpan = 2;
fFrameSlider.setLayoutData(gd2);
fFrameSlider.setValues(0, 0, 100, 1, 1, 10);
fFrameSlider.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
IHandlerService handlerService = getSite().getService(IHandlerService.class);
if (e.detail == SWT.ARROW_DOWN) {
try {
handlerService.executeCommand("org.eclipse.cdt.dsf.gdb.ui.command.selectNextTraceRecord", null); //$NON-NLS-1$
} catch (Exception ex) {
}
} else if (e.detail == SWT.ARROW_UP) {
try {
handlerService.executeCommand("org.eclipse.cdt.dsf.gdb.ui.command.selectPreviousTraceRecord", null); //$NON-NLS-1$
} catch (Exception ex) {
}
} else if (e.detail == SWT.DRAG) {
// We don't want to query gdb while user drags thumb, just update the label instead
// but postpone actual gdb query to the time thumb is released (e.detail == SWT.NONE)
fFrameNumberLabel.setText(TracepointsMessages.bind(
TracepointsMessages.TraceControlView_frame_dragging,
fFrameSlider.getSelection()));
} else {
fTraceControlModel.setCurrentTraceRecord(Integer.toString(fFrameSlider.getSelection()));
}
}
});
fFrameLabel = new Label(fFrameComposite, SWT.NONE);
fFrameLabel.setText(TracepointsMessages.TraceControlView_frame_label);
fFrameLabel.setLayoutData(new GridData());
fFrameNumberLabel = new Label(fFrameComposite, SWT.NONE);
fFrameNumberLabel.setText(TracepointsMessages.TraceControlView_frame_not_looking);
GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
fFrameNumberLabel.setLayoutData(gd);
}
protected void setFrameLineVisible(boolean visible, ITraceStatusDMData2 traceData) {
fFrameComposite.setVisible(visible);
((GridData)fFrameComposite.getLayoutData()).exclude = !visible;
if (visible) {
fFrameSlider.setMinimum(0);
if (traceData.getNumberOfCollectedFrame() == 0) {
fFrameSlider.setMaximum(1);
} else {
fFrameSlider.setMaximum(traceData.getNumberOfCollectedFrame());
}
int inc = traceData.getNumberOfCollectedFrame() / 20;
fFrameSlider.setPageIncrement(inc <= 1 ? 2 : inc);
String fl = EMPTY_STRING;
if (traceData.getCurrentTraceFrameId() != null) {
fl += TracepointsMessages.bind(TracepointsMessages.TraceControlView_frame_looking,
new Object[] { traceData.getCurrentTraceFrameId(),
Integer.valueOf(traceData.getTracepointNumberForCurrentTraceFrame())} );
int recId = 0;
try {
recId = Integer.parseInt(traceData.getCurrentTraceFrameId());
} catch (NumberFormatException e) {
}
fFrameSlider.setSelection(recId);
} else {
fl += TracepointsMessages.bind(TracepointsMessages.TraceControlView_frame_not_looking, traceData.getNumberOfCollectedFrame());
fFrameSlider.setSelection(0);
}
fFrameNumberLabel.setText(fl);
}
if (traceData != null && traceData != null) {
fFrameSlider.setEnabled(traceData.getNumberOfCollectedFrame() != 0);
}
}
protected void createBufferLine(final Composite parent) {
fBufferComposite = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(3, false);
layout.marginHeight = 0;
fBufferComposite.setLayout(layout);
GridData gd = new GridData(SWT.FILL, SWT.TOP, true, false);
fBufferComposite.setLayoutData(gd);
fBufferComposite.setBackgroundMode(SWT.INHERIT_FORCE);
Label fBufferLabel = new Label(fBufferComposite, SWT.NONE);
fBufferLabel.setText(TracepointsMessages.TraceControlView_buffer_label);
if (cachedBold != null) {
fBufferLabel.setFont(cachedBold);
}
GridData gdBL = new GridData(SWT.FILL, SWT.CENTER, true, false);
fBufferLabel.setLayoutData(gdBL);
fBufferLabel.setBackground(fBufferComposite.getBackground());
fBufferProgress = new CircularProgress(fBufferComposite, SWT.NONE);
GridData bpGd = new GridData(SWT.CENTER, SWT.TOP, false, false);
bpGd.verticalSpan = 2;
fBufferProgress.setLayoutData(bpGd);
fSetCircularBufferButton = new FlatRadioButton(fBufferComposite, SWT.NONE);
fSetCircularBufferButton.setText(TracepointsMessages.TraceControlView_buffer_circular_button_label);
fSetCircularBufferButton.setSelection(false);
fSetCircularBufferButton.setEnabled(true);
fSetCircularBufferButton.setToolTipText(TracepointsMessages.TraceControlView_buffer_circular_off_tooltip);
GridData cbbGd = new GridData(SWT.RIGHT, SWT.CENTER, false, false);
cbbGd.horizontalIndent = 20;
fSetCircularBufferButton.setLayoutData(cbbGd);
fSetCircularBufferButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
fTraceControlModel.setCircularBuffer(fSetCircularBufferButton.getSelection());
fTraceControlModel.updateContent();
}
});
fBufferCollectedFramesLabel = new Label(fBufferComposite, SWT.WRAP);
fBufferCollectedFramesLabel.setText(TracepointsMessages.TraceControlView_buffer_label);
GridData gd3 = new GridData(SWT.FILL, SWT.BOTTOM, true, false);
fBufferCollectedFramesLabel.setLayoutData(gd3);
}
protected void setBufferLineVisible(boolean visible, ITraceStatusDMData2 tData, boolean readonly) {
fBufferComposite.setVisible(visible);
((GridData)fBufferComposite.getLayoutData()).exclude = !visible;
if (visible && tData != null){
if (tData.getStopReason() != null && tData.getStopReason() == STOP_REASON_ENUM.OVERFLOW){
// Buffer overflowed, it should be 100% full instead of 99%
fBufferProgress.setProgress(100);
} else if (tData.getStopReason() != null && tData.isCircularBuffer() && tData.getNumberOfCreatedFrames() > tData.getNumberOfCollectedFrame()) {
// Buffer is circular and overflowed once, it should be 100% full instead of 99%
fBufferProgress.setProgress(100);
} else if (tData.isCircularBuffer() && tData.isTracingActive() &&
tData.getNumberOfCreatedFrames() > tData.getNumberOfCollectedFrame()) {
// If we run with Circular buffer and all buffer was filled in once, we continue displaying progress 100%
// and showing moving bar that makes a circle every tData.getNumberOfCollectedFrame() because it is buffer size in frames
// and actual number of collected frames from the start is tData.getNumberOfCreatedFrames(), but only last
// tData.getNumberOfCollectedFrame() are stored in the buffer
int p = (tData.getNumberOfCreatedFrames() % tData.getNumberOfCollectedFrame()) * 100 / tData.getNumberOfCollectedFrame();
// 100 is an indicator that buffer is already full and should be showed in different manner
fBufferProgress.setProgress(100 + p);
} else {
fBufferProgress.setProgress((tData.getTotalBufferSize() - tData.getFreeBufferSize()) * 100 / tData.getTotalBufferSize());
}
fSetCircularBufferButton.setSelection(tData.isCircularBuffer());
fSetCircularBufferButton.setEnabled(!readonly);
fSetCircularBufferButton.setToolTipText(fSetCircularBufferButton.getSelection() ?
TracepointsMessages.TraceControlView_buffer_circular_on_tooltip :
TracepointsMessages.TraceControlView_buffer_circular_off_tooltip);
fSetCircularBufferButton.redraw();
fSetCircularBufferButton.update();
fBufferCollectedFramesLabel.setText(TracepointsMessages.bind(
TracepointsMessages.TraceControlView_buffer_frames_collected,
tData.getNumberOfCollectedFrame(),
(tData.getTotalBufferSize() - tData.getFreeBufferSize())/1000));
fBufferProgress.redraw();
fBufferProgress.update();
}
}
protected void createActions() {
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
window.getActivePage().showActionSet("org.eclipse.cdt.debug.ui.tracepointActionSet"); //$NON-NLS-1$
IActionBars bars = getViewSite().getActionBars();
IToolBarManager manager = bars.getToolBarManager();
// Create the action to refresh the view
fRefreshViewAction = new RefreshViewAction();
bars.setGlobalActionHandler(ActionFactory.REFRESH.getId(), fRefreshViewAction);
manager.add(fRefreshViewAction);
fRefreshViewAction.setEnabled(false);
fAutoRefreshAction = new AutoRefreshAction();
manager.add(fAutoRefreshAction);
fAutoRefreshAction.setChecked(true);
fAutoRefreshAction.setEnabled(true);
fAutoRefreshEnabled = true;
fLastRefreshTime = System.currentTimeMillis();
fDisconnectedTracingAction = new DisconnectedTracingAction();
manager.add(fDisconnectedTracingAction);
fDisconnectedTracingAction.setEnabled(false);
// Create the action to open the trace variable details
fOpenTraceVarDetails = new OpenTraceVarDetailsAction();
manager.add(fOpenTraceVarDetails);
// Create the action to exit visualization mode
fExitVisualizationAction = new ExitVisualizationModeDetailsAction();
manager.add(fExitVisualizationAction);
bars.updateActionBars();
updateActionEnablement(null);
}
@Override
public void dispose() {
fTraceControlModel.dispose();
fStatusLabel = null; // Indicate that we have been disposed
if (refreshUIJob != null) {
refreshUIJob.cancel();
}
if (cachedBold != null) {
cachedBold.dispose();
cachedBold = null;
}
super.dispose();
}
protected void updateUI(final String statusMessage) {
try {
fLastTraceData = null;
setSecondaryStatusLineVisible(false, null);
//setNotesLineVisible(false, null, false);
setFrameLineVisible(false, null);
setBufferLineVisible(false, null, false);
fStatusLabel.setText(statusMessage);
setActionLinkVisible(false, EMPTY_STRING);
updateActionEnablement(null);
updateLayout();
fDisconnectedTracingAction.setEnabled(false);
} catch (SWTException ex) {
}
}
protected void updateUI(final ITraceStatusDMData2 traceData) {
fLastTraceData = traceData;
if (traceData == null ) {
// should not happen, but still process it correctly
updateUI(TracepointsMessages.TraceControlView_trace_status_inactive);
} else if (!traceData.isTracingSupported()) {
updateUI(TracepointsMessages.TraceControlView_trace_status_not_supported);
} else if (traceData.isTracingFromFile()) {
// Off-line tracing from data file
fDisconnectedTracingAction.setEnabled(false);
String s = TracepointsMessages.TraceControlView_trace_status_offline;
fStatusLabel.setText(s);
setActionLinkVisible(false, EMPTY_STRING);
// If start and stop time are not available in trace data file, do not show secondary status line
if (getTimeMilliseconds(traceData.getStartTime()) != 0 && getTimeMilliseconds(traceData.getStopTime()) != 0) {
setSecondaryStatusLineVisible(true, traceData);
} else {
setSecondaryStatusLineVisible(false, traceData);
}
//setNotesLineVisible(true, traceData, true);
setBufferLineVisible(true, traceData, true);
setFrameLineVisible(true, traceData);
updateActionEnablement(traceData);
updateLayout();
} else if (!traceData.isTracingActive() && traceData.getStopReason() == null){
// Tracing is not started yet
fDisconnectedTracingAction.setEnabled(true);
fStatusLabel.setText(TracepointsMessages.TraceControlView_trace_status_not_started);
setActionLinkVisible(true,TracepointsMessages.TraceControlView_action_start);
setSecondaryStatusLineVisible(false, null);
//setNotesLineVisible(true, traceData, false);
setBufferLineVisible(true, traceData, false);
setFrameLineVisible(false, null);
updateActionEnablement(traceData);
updateLayout();
} else {
// Live execution tracing started and running or started and stopped
fDisconnectedTracingAction.setEnabled(true);
// If stopped, stop reason, time and note.
STOP_REASON_ENUM fStopReason = traceData.getStopReason();
if (fStopReason != null) {
// Tracing has stopped we need notes, secondary status line, and frames slider
setSecondaryStatusLineVisible(true, traceData);
//setNotesLineVisible(true, traceData, false);
setFrameLineVisible(true, traceData);
setBufferLineVisible(true, traceData, false);
if (traceData.getCurrentTraceFrameId() != null) {
fStatusLabel.setText(TracepointsMessages.TraceControlView_trace_status_visualization);
setActionLinkVisible(true, TracepointsMessages.TraceControlView_action_finish_visualization);
} else {
if (traceData.getNumberOfCollectedFrame() == 0) {
fStatusLabel.setText(TracepointsMessages.TraceControlView_trace_status_not_started);
} else {
fStatusLabel.setText(TracepointsMessages.TraceControlView_trace_status_stopped);
}
setActionLinkVisible(true, TracepointsMessages.TraceControlView_action_restart);
}
} else {
// Tracing is running, don't show stop reason line, stop notes and frames line.
String s = TracepointsMessages.TraceControlView_trace_status_in_progress;
fStatusLabel.setText(s);
setActionLinkVisible(true, TracepointsMessages.TraceControlView_action_stop);
setSecondaryStatusLineVisible(true, traceData);
//setNotesLineVisible(true, traceData, false);
setFrameLineVisible(false, traceData);
setBufferLineVisible(true, traceData, true);
startRefreshUIJob();
}
updateActionEnablement(traceData);
updateLayout();
}
}
protected void startRefreshUIJob() {
if (refreshUIJob == null) {
refreshUIJob = new UIJob("Refresh Trace Control view UI") { //$NON-NLS-1$
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
// Run on the UI thread to avoid synchronization
if (fAutoRefreshEnabled) {
fTraceControlModel.updateContent();
} else {
// Update the UI to simply say how long ago was the last refresh
updateUI(fLastTraceData);
}
return Status.OK_STATUS;
}
};
}
refreshUIJob.schedule(UI_REFRESH_DELAY);
}
protected String getStopMessage(ITraceStatusDMData2 tData) {
String stopMessage;
STOP_REASON_ENUM fStopReason = tData.getStopReason();
if (fStopReason == STOP_REASON_ENUM.REQUEST) {
stopMessage = TracepointsMessages.TraceControlView_tracing_stopped_user_request;
} else if (fStopReason == STOP_REASON_ENUM.PASSCOUNT) {
if (tData.getStoppingTracepoint() != null) {
stopMessage = TracepointsMessages.bind(TracepointsMessages.TraceControlView_tracing_stopped_tracepoint_number, tData.getStoppingTracepoint());
} else {
stopMessage = TracepointsMessages.TraceControlView_tracing_stopped_passcount;
}
} else if (fStopReason == STOP_REASON_ENUM.OVERFLOW) {
stopMessage = TracepointsMessages.TraceControlView_tracing_stopped_buffer_full;
} else if (fStopReason == STOP_REASON_ENUM.DISCONNECTION) {
stopMessage = TracepointsMessages.TraceControlView_tracing_stopped_disconnection;
} else if (fStopReason == STOP_REASON_ENUM.ERROR) {
stopMessage = TracepointsMessages.TraceControlView_tracing_stopped_error;
} else {
stopMessage = TracepointsMessages.TraceControlView_tracing_stopped_unknown;
}
String user = EMPTY_STRING;
if (tData.getUserName() != null && tData.getUserName().length() > 0) {
user = TracepointsMessages.bind(TracepointsMessages.TraceControlView_trace_status_secondary_user, tData.getUserName());
}
if (tData.isTracingFromFile()) {
stopMessage = TracepointsMessages.bind(
TracepointsMessages.TraceControlView_trace_status_secondary_offline,
new Object[] {formatTime(tData.getStartTime()),
user,
formatTime(tData.getStopTime()),
stopMessage
});
} else {
stopMessage = TracepointsMessages.bind(
TracepointsMessages.TraceControlView_trace_status_secondary_stopped,
new Object[] {formatTimeInterval(tData.getStartTime(),tData.getStopTime()),
user,
formatTime(tData.getStopTime()),
stopMessage
});
}
return stopMessage;
}
protected void updateActionEnablement(ITraceStatusDMData2 traceData) {
fOpenTraceVarDetails.setEnabled(traceData != null && traceData.isTracingSupported());
fExitVisualizationAction.setEnabled(traceData != null && traceData.getCurrentTraceFrameId() != null &&
!traceData.isTracingFromFile());
fDisconnectedTracingAction.setChecked(traceData != null && traceData.isDisconnectedTracingEnabled());
}
@Override
public void setFocus() {
if (fStatusLabel != null) {
fStatusLabel.setFocus();
}
}
public void updateLayout() {
fStatusComposite.layout(true);
fTopComposite.layout(true);
}
protected long getTimeMilliseconds(String time) {
long microseconds = 0;
try {
if (time.length() != 0) {
String[] times = time.split("\\."); //$NON-NLS-1$
microseconds += Long.parseLong(times[0]) * 1000000;
microseconds += Long.parseLong(times[1]);
}
} catch (NumberFormatException ex) {
GdbPlugin.log(ex);
}
return microseconds / 1000;
}
/**
* Format time from gdb presentation into user-understandable form
* @param time in gd presentation
* @return
*/
protected String formatTime(String time) {
long milliseconds = getTimeMilliseconds(time);
return formatTime(milliseconds);
}
/**
* Format time from standard milliseconds since Epoch into user-understandable form
*/
protected String formatTime(long milliseconds) {
Date date = new Date(milliseconds);
long currentTime = System.currentTimeMillis();
long days = TimeUnit.MILLISECONDS.toDays(currentTime - milliseconds);
if (days == 0) {
// today
return TracepointsMessages.bind(TracepointsMessages.TraceControlView_today, DateFormat.getTimeInstance(DateFormat.SHORT).format(date));
} else if (days == 1) {
// yesterday
return TracepointsMessages.bind(TracepointsMessages.TraceControlView_yesterday, DateFormat.getTimeInstance(DateFormat.SHORT).format(date));
}
return DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(date);
}
/**
* Format time interval returned by trace status command into human-readable
*/
protected String formatTimeInterval(String startTime, String stopTime) {
long startMicroseconds = 0;
long stopMicroseconds = 0;
try {
if (startTime.length() != 0) {
String[] times = startTime.split("\\."); //$NON-NLS-1$
startMicroseconds += Long.parseLong(times[0]) * 1000000;
startMicroseconds += Long.parseLong(times[1]);
}
if (stopTime.length() != 0) {
String[] times = stopTime.split("\\."); //$NON-NLS-1$
stopMicroseconds += Long.parseLong(times[0]) * 1000000;
stopMicroseconds += Long.parseLong(times[1]);
}
return formatTimeInterval(startMicroseconds/1000, stopMicroseconds/1000, true);
} catch (NumberFormatException ex) {
GdbPlugin.log(ex);
}
return EMPTY_STRING;
}
/**
* Format time interval returned by trace status command into human-readable
*/
protected String formatTimeInterval(long startMilliseconds, long stopMilliseconds, boolean shortForm) {
long millis = stopMilliseconds - startMilliseconds;
long days = TimeUnit.MILLISECONDS.toDays(millis);
millis -= TimeUnit.DAYS.toMillis(days);
long hours = TimeUnit.MILLISECONDS.toHours(millis);
millis -= TimeUnit.HOURS.toMillis(hours);
long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
millis -= TimeUnit.MINUTES.toMillis(minutes);
long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
StringBuilder sb = new StringBuilder(64);
if (!shortForm) {
if (days != 0) sb.append(days).append(TracepointsMessages.TraceControlView_date_days);
if (hours != 0) sb.append(hours).append(TracepointsMessages.TraceControlView_date_hours);
if (minutes != 0) sb.append(minutes).append(TracepointsMessages.TraceControlView_date_minutes);
if (seconds != 0) sb.append(seconds).append(TracepointsMessages.TraceControlView_date_seconds);
if (sb.length() == 0) sb.append(TracepointsMessages.TraceControlView_date_zero);
} else {
if (days != 0) sb.append(days).append(TracepointsMessages.TraceControlView_date_short_days);
if (hours != 0) sb.append(hours).append(TracepointsMessages.TraceControlView_date_short_hours);
if (minutes != 0) sb.append(minutes).append(TracepointsMessages.TraceControlView_date_short_minutes);
if (seconds != 0) sb.append(seconds).append(TracepointsMessages.TraceControlView_date_short_seconds);
if (sb.length() == 0) sb.append(TracepointsMessages.TraceControlView_date_short_zero);
}
return(sb.toString());
}
/**
* GDB's set trace-user and set trace-notes commands require quotes if argument contains spaces,
* but these quotes are returned by trace status, to workaround this we remove quotes on UI side
*/
protected String removeQuotes(String s) {
if (s.startsWith("\"") && s.endsWith("\"")) { //$NON-NLS-1$//$NON-NLS-2$
return s.substring(1, s.length()-1);
} else {
return s;
}
}
}