From a5823d5fd013de14190b8e1ba55ba69ab4252d2c Mon Sep 17 00:00:00 2001 From: Alvaro Sanchez-Leon Date: Mon, 26 Apr 2010 15:00:15 +0000 Subject: [PATCH] April 26th, 2010 [Bug 310200] [TMF] Time Analysis Viewer widget improvements and bug fixes --- .../timeAnalysis/ITimeAnalysisViewer.java | 4 +- .../tmf/ui/viewers/timeAnalysis/Messages.java | 5 +- .../timeAnalysis/TmfTimeAnalysisProvider.java | 57 +- .../timeAnalysis/TmfTimeAnalysisViewer.java | 92 ++- .../viewers/timeAnalysis/messages.properties | 3 +- .../widgets/ITimeDataProvider.java | 11 +- .../timeAnalysis/widgets/TimeScaleCtrl.java | 566 ++++++++++++++---- .../widgets/TmfTimeStatesCtrl.java | 233 +++---- .../widgets/TmfTimeTipHandler.java | 74 ++- .../widgets/TraceColorScheme.java | 37 +- .../viewers/timeAnalysis/widgets/Utils.java | 112 ++-- 11 files changed, 775 insertions(+), 419 deletions(-) diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITimeAnalysisViewer.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITimeAnalysisViewer.java index d0d32d6628..d1bb5ada04 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITimeAnalysisViewer.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITimeAnalysisViewer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009 Ericsson + * Copyright (c) 2009, 2010 Ericsson * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which @@ -162,4 +162,6 @@ public interface ITimeAnalysisViewer extends ITmfViewer { */ public void waitCursor(boolean waitInd); + public void setFocus(); + } \ No newline at end of file diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/Messages.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/Messages.java index c02a986381..32e1dd3ff7 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/Messages.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/Messages.java @@ -1,5 +1,5 @@ /********************************************************************** - * Copyright (c) 2005, 2008, 2009 IBM Corporation, Intel Corporation, Ericsson + * Copyright (c) 2005, 2008, 2009, 2010 IBM Corporation, Intel Corporation, Ericsson * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -26,6 +26,7 @@ public class Messages { public static String _TRACE_CLASS_NAME; public static String _TRACE_GROUP_NAME; public static String _TRACE_START_TIME; + public static String _TRACE_EVENT_TIME; public static String _TRACE_DATE; public static String _TRACE_STOP_TIME; public static String _TRACE_STATE; @@ -34,7 +35,7 @@ public class Messages { public static String _TRACE_FILTER_DESC; // misc public static String _Timescale; - public static String _DURATION; + public static String _DURATION; public static String _UNDEFINED_GROUP; public static String _TRACE_GROUP_LABEL; public static String _EDIT_PROFILING_OPTIONS; diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeAnalysisProvider.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeAnalysisProvider.java index 4f4a49d840..ce95945b14 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeAnalysisProvider.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeAnalysisProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009 Ericsson + * Copyright (c) 2009, 2010 Ericsson * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which @@ -15,8 +15,6 @@ package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis; import java.util.List; import java.util.Map; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.linuxtools.tmf.ui.TmfUiPlugin; import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent; import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.TimeEvent; @@ -25,7 +23,6 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.ui.plugin.AbstractUIPlugin; public abstract class TmfTimeAnalysisProvider { @@ -55,31 +52,31 @@ public abstract class TmfTimeAnalysisProvider { } } - static private String _externalPath[] = { - "icons/full/obj16/thread_obj.gif", // running thread - "icons/full/obj16/threads_obj.gif", // suspended - "icons/full/obj16/threadt_obj.gif", // stopped - "icons/full/obj16/stckframe_running_obj.gif", // running stack frame - "icons/full/obj16/stckframe_obj.gif", // stack frame - }; - - static private String _externalPlugin[] = { "org.eclipse.debug.ui", - "org.eclipse.debug.ui", "org.eclipse.debug.ui", - "org.eclipse.debug.ui", "org.eclipse.debug.ui", }; - - static private Image getImage(int idx) { - if (idx < 0 || idx >= IMG_NUM) - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - String key = "trace.img." + idx; - Image img = TmfUiPlugin.getDefault().getImageRegistry().get(key); - if (null == img) { - ImageDescriptor desc = AbstractUIPlugin.imageDescriptorFromPlugin( - _externalPlugin[idx], _externalPath[idx]); - TmfUiPlugin.getDefault().getImageRegistry().put(key, desc); - img = TmfUiPlugin.getDefault().getImageRegistry().get(key); - } - return img; - } + // static private String _externalPath[] = { + // "icons/full/obj16/thread_obj.gif", // running thread + // "icons/full/obj16/threads_obj.gif", // suspended + // "icons/full/obj16/threadt_obj.gif", // stopped + // "icons/full/obj16/stckframe_running_obj.gif", // running stack frame + // "icons/full/obj16/stckframe_obj.gif", // stack frame + // }; + // + // static private String _externalPlugin[] = { "org.eclipse.debug.ui", + // "org.eclipse.debug.ui", "org.eclipse.debug.ui", + // "org.eclipse.debug.ui", "org.eclipse.debug.ui", }; + // + // static private Image getImage(int idx) { + // if (idx < 0 || idx >= IMG_NUM) + // SWT.error(SWT.ERROR_INVALID_ARGUMENT); + // String key = "trace.img." + idx; + // Image img = TmfUiPlugin.getDefault().getImageRegistry().get(key); + // if (null == img) { + // ImageDescriptor desc = AbstractUIPlugin.imageDescriptorFromPlugin( + // _externalPlugin[idx], _externalPath[idx]); + // TmfUiPlugin.getDefault().getImageRegistry().put(key, desc); + // img = TmfUiPlugin.getDefault().getImageRegistry().get(key); + // } + // return img; + // } public void drawState(TraceColorScheme colors, ITimeEvent event, Rectangle rect, GC gc, boolean selected, boolean rectBound, @@ -308,6 +305,7 @@ public abstract class TmfTimeAnalysisProvider { * @return */ public Image getItemImage(Object obj) { + /* if (obj instanceof ITmfTimeAnalysisEntry) { List list = ((ITmfTimeAnalysisEntry) obj).getTraceEvents(); if (null != list && list.size() > 0) @@ -320,6 +318,7 @@ public abstract class TmfTimeAnalysisProvider { if (obj instanceof TimeEvent) { return getImage(IMG_THREAD_RUNNING); } + */ return null; } diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeAnalysisViewer.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeAnalysisViewer.java index 5cf3b8d8cf..c829edf569 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeAnalysisViewer.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeAnalysisViewer.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2007, 2008, 2009 Intel Corporation, Ericsson + * Copyright (c) 2007, 2008, 2009, 2010 Intel Corporation, Ericsson * 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 @@ -40,6 +40,7 @@ import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; @@ -76,7 +77,7 @@ public class TmfTimeAnalysisViewer implements ITimeAnalysisViewer, ITimeDataProv // Calender Time format, using Epoch reference or Relative time // format(default private boolean calendarTimeFormat = false; - private int timeScaleBoderWidth = 4; + private int borderWidth = 4; private int timeScaleHeight = 22; /** ctor */ @@ -171,10 +172,17 @@ public class TmfTimeAnalysisViewer implements ITimeAnalysisViewer, ITimeDataProv _colors = new TraceColorScheme(); _dataViewer = new Composite(parent, SWT.NULL); _dataViewer.setLayoutData(GridUtil.createFill()); + GridLayout gl = new GridLayout(); + gl.marginHeight = borderWidth; + gl.marginWidth = 0; + gl.verticalSpacing = 0; + gl.horizontalSpacing = 0; + _dataViewer.setLayout(gl); _timeScaleCtrl = new TimeScaleCtrl(_dataViewer, _colors); _timeScaleCtrl.setTimeProvider(this); - _timeScaleCtrl.setLayoutData(GridUtil.createFill()); + _timeScaleCtrl.setLayoutData(GridUtil.createHorizontalFill()); + _timeScaleCtrl.setHeight(timeScaleHeight); _stateCtrl = new TmfTimeStatesCtrl(_dataViewer, _colors, _utilImplm); @@ -206,13 +214,6 @@ public class TmfTimeAnalysisViewer implements ITimeAnalysisViewer, ITimeDataProv if (r.isEmpty()) return; - // System.out.println("Client Area:" + r); - // timeScaleBoderWidth = 8; - // timeScaleHeight = 22; - _timeScaleCtrl.setBounds(r.x, r.y + timeScaleBoderWidth, r.width, - timeScaleHeight); - _stateCtrl.setBounds(r.x, r.y + timeScaleBoderWidth + timeScaleHeight, - r.width, r.height - timeScaleBoderWidth - timeScaleHeight); int width = r.width; if (_nameWidth > width - _minNameWidth) _nameWidth = width - _minNameWidth; @@ -220,31 +221,33 @@ public class TmfTimeAnalysisViewer implements ITimeAnalysisViewer, ITimeDataProv _nameWidth = _minNameWidth; } - /** Tries to set most convinient time range for display. */ + /** Tries to set most convenient time range for display. */ void setTimeRange(Object traces[]) { _endTime = 0; _beginTime = -1; ITimeEvent event; for (int i = 0; i < traces.length; i++) { - ITmfTimeAnalysisEntry thread = (ITmfTimeAnalysisEntry) traces[i]; - long lastEventTime = thread.getStopTime(); - if (lastEventTime > thread.getStartTime()) { - if (lastEventTime > _endTime) - _endTime = lastEventTime; + ITmfTimeAnalysisEntry entry = (ITmfTimeAnalysisEntry) traces[i]; + if (entry.getStopTime() >= entry.getStartTime() && entry.getStopTime() > 0) { + if (_beginTime < 0 || entry.getStartTime() < _beginTime) { + _beginTime = entry.getStartTime(); + } + if (entry.getStopTime() > _endTime) { + _endTime = entry.getStopTime(); + } } - List list = thread.getTraceEvents(); + List list = entry.getTraceEvents(); int len = list.size(); if (len > 0) { + event = (ITimeEvent) list.get(0); + if (_beginTime < 0 || event.getTime() < _beginTime) { + _beginTime = event.getTime(); + } event = (ITimeEvent) list.get(list.size() - 1); - lastEventTime = event.getTime(); - if (lastEventTime > _endTime) { - _endTime = lastEventTime; - long duration = event.getDuration(); - _endTime += duration > 0 ? duration : 1000000; + long eventEndTime = event.getTime() + (event.getDuration() > 0 ? event.getDuration() : 0); + if (eventEndTime > _endTime) { + _endTime = eventEndTime; } - event = (ITimeEvent) list.get(0); - if (_beginTime < 0 || _beginTime > event.getTime()) - _beginTime = event.getTime(); } } @@ -253,7 +256,8 @@ public class TmfTimeAnalysisViewer implements ITimeAnalysisViewer, ITimeDataProv } void setTimeBounds() { - _time0_ = _beginTime - (long) ((_endTime - _beginTime) * 0.02); + //_time0_ = _beginTime - (long) ((_endTime - _beginTime) * 0.02); + _time0_ = _beginTime; if (_time0_ < 0) _time0_ = 0; // _time1_ = _time0_ + (_endTime - _time0_) * 1.05; @@ -284,8 +288,8 @@ public class TmfTimeAnalysisViewer implements ITimeAnalysisViewer, ITimeDataProv void updateInternalData(ITmfTimeAnalysisEntry[] traces, long start, long end) { if (null == traces) traces = new ITmfTimeAnalysisEntry[0]; - if (end < 1 || start < 1) { - // End or start time are unspecified and need to be determined from + if ((start == 0 && end == 0) || start < 0 || end < 0) { + // Start and end time are unspecified and need to be determined from // individual processes setTimeRange(traces); } else { @@ -301,8 +305,11 @@ public class TmfTimeAnalysisViewer implements ITimeAnalysisViewer, ITimeDataProv */ private void refreshAllData(ITmfTimeAnalysisEntry[] traces) { setTimeBounds(); - if (_selectedTime < 0 || _selectedTime > _endTime) - _selectedTime = _endTime; + if (_selectedTime < _beginTime) { + _selectedTime = _beginTime; + } else if (_selectedTime > _endTime) { + _selectedTime = _endTime; + } _stateCtrl.refreshData(traces); filterOutNotification(); } @@ -381,18 +388,6 @@ public class TmfTimeAnalysisViewer implements ITimeAnalysisViewer, ITimeDataProv return _time0_; } - /* - * (non-Javadoc) - * - * @see - * org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets.ITimeDataProvider - * #mouseUp() - */ - public void mouseUp() { - // refresh listeners with the new selected time if changed - notifyStartFinishTimeSelectionListeners(_time0, _time1); - } - /* * (non-Javadoc) * @@ -451,9 +446,9 @@ public class TmfTimeAnalysisViewer implements ITimeAnalysisViewer, ITimeDataProv _time0 += dt; _time1 += dt; } - if (_time0 < 0) { - _time1 -= _time0; - _time0 = 0; + if (_time0 < _time0_) { + _time1 += _time0_ - _time0; + _time0 = _time0_; } else if (_time1 > _time1_) { _time0 -= _time1 - _time1_; _time1 = _time1_; @@ -699,12 +694,14 @@ public class TmfTimeAnalysisViewer implements ITimeAnalysisViewer, ITimeDataProv } public int getBorderWidth() { - return timeScaleBoderWidth; + return borderWidth; } public void setBorderWidth(int borderWidth) { if (borderWidth > -1) { - this.timeScaleBoderWidth = borderWidth; + this.borderWidth = borderWidth; + GridLayout gl = (GridLayout)_dataViewer.getLayout(); + gl.marginHeight = borderWidth; } } @@ -715,6 +712,7 @@ public class TmfTimeAnalysisViewer implements ITimeAnalysisViewer, ITimeDataProv public void setHeaderHeight(int headerHeight) { if (headerHeight > -1) { this.timeScaleHeight = headerHeight; + _timeScaleCtrl.setHeight(headerHeight); } } diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/messages.properties b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/messages.properties index 3d3413fbad..7dac086b5a 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/messages.properties +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/messages.properties @@ -1,5 +1,5 @@ #******************************************************************************* -# Copyright (c) 2009 Ericsson +# Copyright (c) 2009, 2010 Ericsson # # All rights reserved. This program and the accompanying materials are # made available under the terms of the Eclipse Public License v1.0 which @@ -20,6 +20,7 @@ _TRACE_NAME = Process Name _TRACE_CLASS_NAME = Class Name _TRACE_GROUP_NAME = Group Name _TRACE_START_TIME = Start Time +_TRACE_EVENT_TIME = Event Time _TRACE_STOP_TIME = Stop Time _DURATION = Duration _TRACE_STATE = State diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/ITimeDataProvider.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/ITimeDataProvider.java index 2060aa11c4..7cab4dd51b 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/ITimeDataProvider.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/ITimeDataProvider.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2007, Intel Corporation. + * Copyright (c) 2007, 2010 Intel Corporation. * 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 @@ -8,7 +8,7 @@ * Contributors: * Intel Corporation - Initial API and implementation * Ruslan A. Scherbakov, Intel - Initial API and implementation - * Alvaro Sanchex-Leon - Udpated for TMF + * Alvaro Sanchex-Leon - Updated for TMF * * $Id: ITimeDataProvider.java,v 1.2 2007/02/27 18:37:36 ewchan Exp $ *****************************************************************************/ @@ -33,13 +33,6 @@ public interface ITimeDataProvider { long getMinTimeInterval(); - /** - * Receive Notification when any of the buttons of the mouse switch back to - * up position, this method may trigger time update notification to - * listeners - */ - void mouseUp(); - /** * Updates the time range and notify registered listeners * diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TimeScaleCtrl.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TimeScaleCtrl.java index 1e3a44b40f..7e7ff67063 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TimeScaleCtrl.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TimeScaleCtrl.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2007, 2008 Intel Corporation and others. + * Copyright (c) 2007, 2008, 2010 Intel Corporation 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 @@ -16,7 +16,10 @@ package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets; import java.text.SimpleDateFormat; +import java.util.Calendar; import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.Messages; import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets.Utils.Resolution; @@ -40,6 +43,20 @@ public class TimeScaleCtrl extends TraceCtrl implements MouseListener, addMouseMoveListener(this); } + private static final long SEC_IN_NS = 1000000000; + private static final long MIN_IN_NS = 60 * SEC_IN_NS; + private static final long HOUR_IN_NS = 60 * MIN_IN_NS; + private static final long DAY_IN_NS = 24 * HOUR_IN_NS; + private static final long MONTH_IN_NS = 31 * DAY_IN_NS; // upper limit + private static final long YEAR_IN_NS = 366 * DAY_IN_NS; // upper limit + + private static final double LOG10_1 = Math.log10(1); + private static final double LOG10_2 = Math.log10(2); + private static final double LOG10_3 = Math.log10(3); + private static final double LOG10_5 = Math.log10(5); + + private static final Calendar GREGORIAN_CALENDAR = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT")); + private ITimeDataProvider _timeProvider; private int _dragState = 0; private int _dragX0 = 0; @@ -48,68 +65,108 @@ public class TimeScaleCtrl extends TraceCtrl implements MouseListener, private long _time1bak; private boolean _isInUpdate; private Rectangle _rect0 = new Rectangle(0, 0, 0, 0); + private int _height; public void setTimeProvider(ITimeDataProvider timeProvider) { _timeProvider = timeProvider; } - private double _timeDeltaD; private long _timeDelta; - private void calcTimeDelta(int width, double K) { - long D[] = { 1, 2, 5, }; - long pow = 1; - double powD = 1; - long td = pow; - double tdD = powD; - double dx = tdD * K; - int i = 0; - while (dx < width) { - td = D[i] * pow; - tdD = D[i] * powD; - dx = tdD * K; - i++; - if (i == 3) { - i = 0; - pow *= 10; - powD *= 10; - } - } - _timeDeltaD = tdD; - _timeDelta = td; -// Trace.debug("Width: " + width + " K: " + K + " Time Delta: " -// + _timeDelta); - } - - static private TimeDraw _tds[] = new TimeDraw[] { new TimeDrawSec(), - new TimeDrawMillisec(), new TimeDrawMicrosec(), - new TimeDrawNanosec(), new TimeDrawAbsSec(), - new TimeDrawAbsMillisec(), new TimeDrawAbsMicroSec(), - new TimeDrawAbsNanoSec() }; + @Override + public Point computeSize(int wHint, int hHint, boolean changed) { + return super.computeSize(wHint, _height, changed); + } + + public void setHeight(int height) { + this._height = height; + } + + private void calcTimeDelta(int width, double pixelsPerNanoSec) { + double minDelta = (double) ((pixelsPerNanoSec ==0) ? YEAR_IN_NS : width / pixelsPerNanoSec); + long unit = 1; + if (_timeProvider != null && _timeProvider.isCalendarFormat()) { + if (minDelta > 6 * MONTH_IN_NS) { + unit = YEAR_IN_NS; + } else if (minDelta > 3 * MONTH_IN_NS) { + unit = 6 * MONTH_IN_NS; + } else if (minDelta > 10 * DAY_IN_NS) { + unit = MONTH_IN_NS; + } else if (minDelta > 12 * HOUR_IN_NS) { + unit = DAY_IN_NS; + } else if (minDelta > 3 * HOUR_IN_NS) { + unit = 6 * HOUR_IN_NS; + } else if (minDelta > 30 * MIN_IN_NS) { + unit = HOUR_IN_NS; + } else if (minDelta > 10 * MIN_IN_NS) { + unit = 15 * MIN_IN_NS; + } else if (minDelta > 30 * SEC_IN_NS) { + unit = MIN_IN_NS; + } else if (minDelta > 20 * SEC_IN_NS) { + unit = 30 * SEC_IN_NS; + } + } + double log = Math.log10((double) minDelta / unit); + long pow10 = (long) log; + double remainder = log - pow10; + if (remainder < LOG10_1) { + _timeDelta = (long) Math.pow(10, pow10) * unit; + } else if (remainder < LOG10_2) { + _timeDelta = 2 * (long) Math.pow(10, pow10) * unit; + } else if (remainder < LOG10_3 && unit >= HOUR_IN_NS && unit < YEAR_IN_NS) { + _timeDelta = 3 * (long) Math.pow(10, pow10) * unit; + } else if (remainder < LOG10_5) { + _timeDelta = 5 * (long) Math.pow(10, pow10) * unit; + } else { + _timeDelta = 10 * (long) Math.pow(10, pow10) * unit; + } + } + + private static TimeDraw TIMEDRAW_NANOSEC = new TimeDrawNanosec(); + private static TimeDraw TIMEDRAW_MICROSEC = new TimeDrawMicrosec(); + private static TimeDraw TIMEDRAW_MILLISEC = new TimeDrawMillisec(); + private static TimeDraw TIMEDRAW_SEC = new TimeDrawSec(); + private static TimeDraw TIMEDRAW_ABS_NANOSEC = new TimeDrawAbsNanoSec(); + private static TimeDraw TIMEDRAW_ABS_MICROSEC = new TimeDrawAbsMicroSec(); + private static TimeDraw TIMEDRAW_ABS_MILLISEC = new TimeDrawAbsMillisec(); + private static TimeDraw TIMEDRAW_ABS_SEC = new TimeDrawAbsSec(); + private static TimeDraw TIMEDRAW_ABS_MIN = new TimeDrawAbsMin(); + private static TimeDraw TIMEDRAW_ABS_HRS = new TimeDrawAbsHrs(); + private static TimeDraw TIMEDRAW_ABS_DAY = new TimeDrawAbsDay(); + private static TimeDraw TIMEDRAW_ABS_MONTH = new TimeDrawAbsMonth(); + private static TimeDraw TIMEDRAW_ABS_YEAR = new TimeDrawAbsYear(); TimeDraw getTimeDraw(long timeDelta) { TimeDraw timeDraw; - if (_timeProvider != null) { - if (_timeProvider.isCalendarFormat()) { - if (timeDelta >= 1000000000) - timeDraw = _tds[4]; - else if (timeDelta >= 1000000) - timeDraw = _tds[5]; - else if (timeDelta >= 1000) - timeDraw = _tds[6]; - else - timeDraw = _tds[7]; - return timeDraw; - } + if (_timeProvider != null && _timeProvider.isCalendarFormat()) { + if (timeDelta >= YEAR_IN_NS) + timeDraw = TIMEDRAW_ABS_YEAR; + else if (timeDelta >= MONTH_IN_NS) + timeDraw = TIMEDRAW_ABS_MONTH; + else if (timeDelta >= DAY_IN_NS) + timeDraw = TIMEDRAW_ABS_DAY; + else if (timeDelta >= HOUR_IN_NS) + timeDraw = TIMEDRAW_ABS_HRS; + else if (timeDelta >= MIN_IN_NS) + timeDraw = TIMEDRAW_ABS_MIN; + else if (timeDelta >= SEC_IN_NS) + timeDraw = TIMEDRAW_ABS_SEC; + else if (timeDelta >= 1000000) + timeDraw = TIMEDRAW_ABS_MILLISEC; + else if (timeDelta >= 1000) + timeDraw = TIMEDRAW_ABS_MICROSEC; + else + timeDraw = TIMEDRAW_ABS_NANOSEC; + return timeDraw; } if (timeDelta >= 1000000000) - timeDraw = _tds[0]; + timeDraw = TIMEDRAW_SEC; else if (timeDelta >= 1000000) - timeDraw = _tds[1]; + timeDraw = TIMEDRAW_MILLISEC; else if (timeDelta >= 1000) - timeDraw = _tds[2]; + timeDraw = TIMEDRAW_MICROSEC; else - timeDraw = _tds[3]; + timeDraw = TIMEDRAW_NANOSEC; return timeDraw; } @@ -120,67 +177,71 @@ public class TimeScaleCtrl extends TraceCtrl implements MouseListener, return; GC gc = e.gc; + gc.fillRectangle(rect); + if (null == _timeProvider) { - gc.fillRectangle(rect); return; } - gc.setBackground(_colors.getColor(TraceColorScheme.TOOL_BACKGROUND)); - gc.setForeground(_colors.getColor(TraceColorScheme.TOOL_FOREGROUND)); long time0 = _timeProvider.getTime0(); long time1 = _timeProvider.getTime1(); long selectedTime = _timeProvider.getSelectedTime(); int leftSpace = _timeProvider.getNameSpace(); int timeSpace = _timeProvider.getTimeSpace(); - - if (time1 <= time0 || timeSpace < 2) { - gc.fillRectangle(rect); - return; - } - - int numDigits = calculateDigits(time0, time1); - + + gc.setBackground(_colors.getColor(TraceColorScheme.TOOL_BACKGROUND)); + gc.setForeground(_colors.getColor(TraceColorScheme.TOOL_FOREGROUND)); Utils.init(_rect0, rect); - int labelWidth = gc.getCharWidth('0') * numDigits; - double K = 1; - if (rect.width - leftSpace > 0) { - K = (double) timeSpace / (time1 - time0); - calcTimeDelta(labelWidth, K); - } - TimeDraw timeDraw = getTimeDraw(_timeDelta); - // draw top left area _rect0.width = leftSpace; - gc.fillRectangle(_rect0); _rect0.x += 4; _rect0.width -= 4; if (_rect0.width > 0) { -// TODO: Check if we really need that piece of code... -// if (false && rect.width - leftSpace > 0) -// Utils.drawText(gc, Messages._Timescale + ": " -// + timeDraw.hint(), _rect0, true); -// else - Utils.drawText(gc, Messages._Timescale + ":", _rect0, true); + Utils.drawText(gc, Messages._Timescale + ":", _rect0, true); } + int messageWidth = gc.stringExtent(Messages._Timescale + ":").x + 4; + Rectangle absHeaderRect = new Rectangle(_rect0.x + messageWidth, _rect0.y, _rect0.width - messageWidth, _rect0.height); _rect0.x -= 4; _rect0.width += 4; - + // prepare and draw right rect of the timescale _rect0.x += leftSpace; _rect0.width = rect.width - leftSpace; - + // draw bottom border and erase all other area gc.drawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width - 1, - rect.y + rect.height - 1); + rect.y + rect.height - 1); _rect0.height--; gc.fillRectangle(_rect0); + + if (time1 <= time0 || timeSpace < 2) { + return; + } + + int numDigits = calculateDigits(time0, time1); + + int labelWidth = gc.getCharWidth('0') * numDigits; + double pixelsPerNanoSec = (timeSpace <= 2) ? 0 : + (double) (timeSpace - 2) / (time1 - time0); // 2 pixels less to make sure end time is visible + calcTimeDelta(labelWidth, pixelsPerNanoSec); + + TimeDraw timeDraw = getTimeDraw(_timeDelta); + + // draw zoom rectangle + if (3 == _dragState && null != _timeProvider) { + if (_dragX0 < _dragX) { + gc.drawRectangle(leftSpace + _dragX0, rect.y, _dragX - _dragX0 - 1, rect.height - 8); + } else if (_dragX0 > _dragX) { + gc.drawRectangle(leftSpace + _dragX, rect.y, _dragX0 - _dragX - 1, rect.height - 8); + } + } if (_rect0.isEmpty()) return; // draw selected time - int x = _rect0.x + (int) ((selectedTime - time0) * K); + int x = _rect0.x + (int) ((double)(selectedTime - time0) * pixelsPerNanoSec); if (x >= _rect0.x && x < _rect0.x + _rect0.width) { gc.setForeground(_colors.getColor(TraceColorScheme.SELECTED_TIME)); gc.drawLine(x, _rect0.y + _rect0.height - 6, x, _rect0.y @@ -194,12 +255,23 @@ public class TimeScaleCtrl extends TraceCtrl implements MouseListener, _rect0.y = rect.y; _rect0.height = rect.height - 4; _rect0.width = labelWidth; - long time = (long) (Math.floor(time0 / _timeDeltaD) * _timeDeltaD); + + long time; + if (_timeProvider != null && _timeProvider.isCalendarFormat()) { + time = floorToCalendar(time0, _timeDelta); + } else { + time = (long) (Math.ceil((double) time0 / _timeDelta) * _timeDelta); + } + // long t = (long) (time * 1000000000); - long t = time; int y = _rect0.y + _rect0.height; + + if (_timeProvider != null && _timeProvider.isCalendarFormat()) { + timeDraw.drawAbsHeader(gc, time, absHeaderRect); + } + while (true) { - x = rect.x + leftSpace + (int) ((time - time0) * K); + x = rect.x + leftSpace + (int) (Math.floor((time - time0) * pixelsPerNanoSec)); if (x >= rect.x + leftSpace + rect.width - _rect0.width) { break; } @@ -207,13 +279,59 @@ public class TimeScaleCtrl extends TraceCtrl implements MouseListener, gc.drawLine(x, y, x, y + 4); _rect0.x = x; if (x + _rect0.width <= rect.x + rect.width) - timeDraw.draw(gc, t, _rect0); + timeDraw.draw(gc, time, _rect0); + } + if (pixelsPerNanoSec == 0 || time > Long.MAX_VALUE - _timeDelta) { + break; } - time += _timeDeltaD; - t += _timeDelta; + time += _timeDelta; + if (_timeProvider != null && _timeProvider.isCalendarFormat()) { + if (_timeDelta >= YEAR_IN_NS) { + GREGORIAN_CALENDAR.setTime(new Date(time / 1000000)); + GREGORIAN_CALENDAR.set(Calendar.MONTH, 0); // January 1st of year + GREGORIAN_CALENDAR.set(Calendar.DAY_OF_MONTH, 1); + time = GREGORIAN_CALENDAR.getTimeInMillis() * 1000000; + } else if (_timeDelta >= MONTH_IN_NS) { + GREGORIAN_CALENDAR.setTime(new Date(time / 1000000)); + GREGORIAN_CALENDAR.set(Calendar.DAY_OF_MONTH, 1); // 1st of month + time = GREGORIAN_CALENDAR.getTimeInMillis() * 1000000; + } + } } } + private long floorToCalendar(long time, long timeDelta) { + if (_timeDelta >= YEAR_IN_NS) { + GREGORIAN_CALENDAR.setTime(new Date(time / 1000000)); + int year = GREGORIAN_CALENDAR.get(Calendar.YEAR); + int yearDelta = (int) (timeDelta / YEAR_IN_NS); + year = (year / yearDelta) * yearDelta; + GREGORIAN_CALENDAR.set(Calendar.YEAR, year); + GREGORIAN_CALENDAR.set(Calendar.MONTH, 0); // January 1st of year + GREGORIAN_CALENDAR.set(Calendar.DAY_OF_MONTH, 1); + GREGORIAN_CALENDAR.set(Calendar.HOUR_OF_DAY, 0); + GREGORIAN_CALENDAR.set(Calendar.MINUTE, 0); + GREGORIAN_CALENDAR.set(Calendar.SECOND, 0); + GREGORIAN_CALENDAR.set(Calendar.MILLISECOND, 0); + time = GREGORIAN_CALENDAR.getTimeInMillis() * 1000000; + } else if (_timeDelta >= MONTH_IN_NS) { + GREGORIAN_CALENDAR.setTime(new Date(time / 1000000)); + int month = GREGORIAN_CALENDAR.get(Calendar.MONTH); + int monthDelta = (int) (timeDelta / MONTH_IN_NS); + month = (month / monthDelta) * monthDelta; + GREGORIAN_CALENDAR.set(Calendar.MONTH, month); + GREGORIAN_CALENDAR.set(Calendar.DAY_OF_MONTH, 1); // 1st of month + GREGORIAN_CALENDAR.set(Calendar.HOUR_OF_DAY, 0); + GREGORIAN_CALENDAR.set(Calendar.MINUTE, 0); + GREGORIAN_CALENDAR.set(Calendar.SECOND, 0); + GREGORIAN_CALENDAR.set(Calendar.MILLISECOND, 0); + time = GREGORIAN_CALENDAR.getTimeInMillis() * 1000000; + } else { + time = (time / timeDelta) * timeDelta; + } + return time; + } + private int calculateDigits(long time0, long time1) { int numDigits = 5; long timeRange = time1 - time0; @@ -222,7 +340,7 @@ public class TimeScaleCtrl extends TraceCtrl implements MouseListener, // Calculate the number of digits to represent the minutes provided // 11:222 // HH:mm:ss - numDigits += 5; + numDigits += 8; if (timeRange < 10000) { // HH:11:222:333:444__ numDigits += 10; @@ -254,65 +372,87 @@ public class TimeScaleCtrl extends TraceCtrl implements MouseListener, } public void mouseDown(MouseEvent e) { - if (1 == e.button && null != _timeProvider) { - setCapture(true); - _dragState = 1; - } - // Window adjustment allowed using mouse button three. - _dragX = _dragX0 = e.x - _timeProvider.getNameSpace(); - _time0bak = _timeProvider.getTime0(); - _time1bak = _timeProvider.getTime1(); + if (_dragState == 0 && null != _timeProvider) { + if (1 == e.button) { + setCapture(true); + _dragState = 1; + } else if (3 == e.button) { + _dragState = 3; + } + int x = e.x - _timeProvider.getNameSpace(); + if (x < 0) { + x = 0; + } else if (x > getSize().x - _timeProvider.getNameSpace()) { + x = getSize().x - _timeProvider.getNameSpace(); + } + _dragX = _dragX0 = x; + _time0bak = _timeProvider.getTime0(); + _time1bak = _timeProvider.getTime1(); + } } public void mouseUp(MouseEvent e) { - if (1 == _dragState) { + if (e.button == 1 && _dragState == 1) { setCapture(false); _dragState = 0; - } - - if (3 == e.button && null != _timeProvider) { - if (_dragX0 < 0) { + } else if (e.button == 3 && _dragState == 3 && null != _timeProvider) { + _dragState = 0; + if (_dragX0 == _dragX) { return; } - Point size = getSize(); - + int timeSpace = _timeProvider.getTimeSpace(); int leftSpace = _timeProvider.getNameSpace(); int x = e.x - leftSpace; - if (x > 0 && size.x > leftSpace && _dragX != x) { + if (timeSpace > 0) { _dragX = x; - long time0 = _time0bak + ((_time1bak - _time0bak) * _dragX0) - / (size.x - leftSpace); - long time1 = _time0bak + ((_time1bak - _time0bak) * _dragX) - / (size.x - leftSpace); + if (_dragX0 > _dragX) { // drag right to left + _dragX = _dragX0; + _dragX0 = x; + } + long time0 = _time0bak + (long) ((_time1bak - _time0bak) * ((double) _dragX0 / timeSpace)); + long time1 = _time0bak + (long) ((_time1bak - _time0bak) * ((double) _dragX / timeSpace)); _timeProvider.setStartFinishTime(time0, time1); + _time0bak = _timeProvider.getTime0(); + _time1bak = _timeProvider.getTime1(); } } // Notify time provider to check the need for listener notification - _timeProvider.mouseUp(); + _timeProvider.setStartFinishTimeNotify(_timeProvider.getTime0(), _timeProvider.getTime1()); } public void mouseMove(MouseEvent e) { - if (_dragX0 < 0) { + if (_dragX0 < 0 || _dragState == 0) { return; } Point size = getSize(); + int leftSpace = _timeProvider.getNameSpace(); + int timeSpace = _timeProvider.getTimeSpace(); + int x = e.x - leftSpace; if (1 == _dragState && null != _timeProvider) { - int leftSpace = _timeProvider.getNameSpace(); - int x = e.x - leftSpace; if (x > 0 && size.x > leftSpace && _dragX != x) { _dragX = x; - long time1 = _time0bak + ((_time1bak - _time0bak) * _dragX0) - / _dragX; + long time1 = _time0bak + (long) ((_time1bak - _time0bak) * ((double) _dragX0 / _dragX)); _timeProvider.setStartFinishTime(_time0bak, time1); } + } else if (3 == _dragState && null != _timeProvider) { + if (x < 0) { + _dragX = 0; + } else if (x > timeSpace) { + _dragX = timeSpace; + } else { + _dragX = x; + } + redraw(); } } public void mouseDoubleClick(MouseEvent e) { if (null != _timeProvider) { _timeProvider.resetStartFinishTime(); + _time0bak = _timeProvider.getTime0(); + _time1bak = _timeProvider.getTime1(); } } } @@ -321,7 +461,28 @@ abstract class TimeDraw { static String S = ":"; static String S0 = ":0"; static String S00 = ":00"; - protected SimpleDateFormat stimeformat = new SimpleDateFormat("HH:mm:ss"); + protected static final SimpleDateFormat stimeformat = new SimpleDateFormat("HH:mm:ss"); + protected static final SimpleDateFormat stimeformatheader = new SimpleDateFormat("yyyy MMM dd"); + protected static final SimpleDateFormat sminformat = new SimpleDateFormat("HH:mm"); + protected static final SimpleDateFormat sminformatheader = new SimpleDateFormat("yyyy MMM dd"); + protected static final SimpleDateFormat shrsformat = new SimpleDateFormat("MMM dd HH:mm"); + protected static final SimpleDateFormat shrsformatheader = new SimpleDateFormat("yyyy"); + protected static final SimpleDateFormat sdayformat = new SimpleDateFormat("MMM dd"); + protected static final SimpleDateFormat sdayformatheader = new SimpleDateFormat("yyyy"); + protected static final SimpleDateFormat smonthformat = new SimpleDateFormat("yyyy MMM"); + protected static final SimpleDateFormat syearformat = new SimpleDateFormat("yyyy"); + static { + stimeformat.setTimeZone(TimeZone.getTimeZone("GMT")); + stimeformatheader.setTimeZone(TimeZone.getTimeZone("GMT")); + sminformat.setTimeZone(TimeZone.getTimeZone("GMT")); + sminformatheader.setTimeZone(TimeZone.getTimeZone("GMT")); + shrsformat.setTimeZone(TimeZone.getTimeZone("GMT")); + shrsformatheader.setTimeZone(TimeZone.getTimeZone("GMT")); + sdayformat.setTimeZone(TimeZone.getTimeZone("GMT")); + sdayformatheader.setTimeZone(TimeZone.getTimeZone("GMT")); + smonthformat.setTimeZone(TimeZone.getTimeZone("GMT")); + syearformat.setTimeZone(TimeZone.getTimeZone("GMT")); + } static String pad(long n) { String s = S; @@ -332,8 +493,13 @@ abstract class TimeDraw { return s + n; } - public abstract void draw(GC gc, long time, Rectangle rect); + public abstract void draw(GC gc, long time, Rectangle rect); + public void drawAbsHeader(GC gc, long time, Rectangle absHeaderRect) { + // Override to draw absolute time header + // This is for the time information not shown in the draw of each tick + } + public abstract String hint(); } @@ -408,19 +574,135 @@ class TimeDrawNanosec extends TimeDraw { } } -class TimeDrawAbsSec extends TimeDraw { - static String _hint = "HH:mm:ss"; +class TimeDrawAbsYear extends TimeDraw { + static String _hint = "YYYY"; - @Override - public void draw(GC gc, long time, Rectangle rect) { - String stime = stimeformat.format(new Date((long) (time * 1E-6))); - Utils.drawText(gc, stime, rect, true); - } + @Override + public void draw(GC gc, long time, Rectangle rect) { + String stime = syearformat.format(new Date((long) (time / 1000000))); + Utils.drawText(gc, stime, rect, true); + } - @Override - public String hint() { - return _hint; - } + @Override + public String hint() { + return _hint; + } +} + +class TimeDrawAbsMonth extends TimeDraw { + static String _hint = "YYYY Mmm"; + + @Override + public void draw(GC gc, long time, Rectangle rect) { + String stime = smonthformat.format(new Date((long) (time / 1000000))); + Utils.drawText(gc, stime, rect, true); + } + + @Override + public String hint() { + return _hint; + } +} + +class TimeDrawAbsDay extends TimeDraw { + static String _hint = "Mmm dd"; + + @Override + public void draw(GC gc, long time, Rectangle rect) { + String stime = sdayformat.format(new Date((long) (time / 1000000))); + Utils.drawText(gc, stime, rect, true); + } + + @Override + public void drawAbsHeader(GC gc, long time, Rectangle rect) { + String header = sdayformatheader.format(new Date((long) (time / 1000000))); + int headerwidth = gc.stringExtent(header).x + 4; + if (headerwidth <= rect.width) { + rect.x += (rect.width - headerwidth); + Utils.drawText(gc, header, rect, true); + } + } + + @Override + public String hint() { + return _hint; + } +} + +class TimeDrawAbsHrs extends TimeDraw { + static String _hint = "Mmm dd HH:mm"; + + @Override + public void draw(GC gc, long time, Rectangle rect) { + String stime = shrsformat.format(new Date((long) (time / 1000000))); + Utils.drawText(gc, stime, rect, true); + } + + @Override + public void drawAbsHeader(GC gc, long time, Rectangle rect) { + String header = shrsformatheader.format(new Date((long) (time / 1000000))); + int headerwidth = gc.stringExtent(header).x + 4; + if (headerwidth <= rect.width) { + rect.x += (rect.width - headerwidth); + Utils.drawText(gc, header, rect, true); + } + } + + @Override + public String hint() { + return _hint; + } +} + +class TimeDrawAbsMin extends TimeDraw { + static String _hint = "HH:mm"; + + @Override + public void draw(GC gc, long time, Rectangle rect) { + String stime = sminformat.format(new Date((long) (time / 1000000))); + Utils.drawText(gc, stime, rect, true); + } + + @Override + public void drawAbsHeader(GC gc, long time, Rectangle rect) { + String header = sminformatheader.format(new Date((long) (time / 1000000))); + int headerwidth = gc.stringExtent(header).x + 4; + if (headerwidth <= rect.width) { + rect.x += (rect.width - headerwidth); + Utils.drawText(gc, header, rect, true); + } + } + + + @Override + public String hint() { + return _hint; + } +} + +class TimeDrawAbsSec extends TimeDraw { + static String _hint = "HH:mm:ss"; + + @Override + public void draw(GC gc, long time, Rectangle rect) { + String stime = stimeformat.format(new Date((long) (time / 1000000))); + Utils.drawText(gc, stime, rect, true); + } + + @Override + public void drawAbsHeader(GC gc, long time, Rectangle rect) { + String header = stimeformatheader.format(new Date((long) (time / 1000000))); + int headerwidth = gc.stringExtent(header).x + 4; + if (headerwidth <= rect.width) { + rect.x += (rect.width - headerwidth); + Utils.drawText(gc, header, rect, true); + } + } + + @Override + public String hint() { + return _hint; + } } class TimeDrawAbsMillisec extends TimeDraw { @@ -428,12 +710,22 @@ class TimeDrawAbsMillisec extends TimeDraw { @Override public void draw(GC gc, long time, Rectangle rect) { - String stime = stimeformat.format(new Date((long) (time * 1E-6))); + String stime = stimeformat.format(new Date((long) (time / 1000000))); String ns = Utils.formatNs(time, Resolution.MILLISEC); Utils.drawText(gc, stime + " " + ns, rect, true); } + @Override + public void drawAbsHeader(GC gc, long time, Rectangle rect) { + String header = stimeformatheader.format(new Date((long) (time / 1000000))); + int headerwidth = gc.stringExtent(header).x + 4; + if (headerwidth <= rect.width) { + rect.x += (rect.width - headerwidth); + Utils.drawText(gc, header, rect, true); + } + } + @Override public String hint() { return _hint; @@ -445,11 +737,21 @@ class TimeDrawAbsMicroSec extends TimeDraw { @Override public void draw(GC gc, long time, Rectangle rect) { - String stime = stimeformat.format(new Date((long) (time * 1E-6))); + String stime = stimeformat.format(new Date((long) (time / 1000000))); String micr = Utils.formatNs(time, Resolution.MICROSEC); Utils.drawText(gc, stime + " " + micr, rect, true); } + @Override + public void drawAbsHeader(GC gc, long time, Rectangle rect) { + String header = stimeformatheader.format(new Date((long) (time / 1000000))); + int headerwidth = gc.stringExtent(header).x + 4; + if (headerwidth <= rect.width) { + rect.x += (rect.width - headerwidth); + Utils.drawText(gc, header, rect, true); + } + } + @Override public String hint() { return _hint; @@ -461,11 +763,21 @@ class TimeDrawAbsNanoSec extends TimeDraw { @Override public void draw(GC gc, long time, Rectangle rect) { - String stime = stimeformat.format(new Date((long) (time * 1E-6))); + String stime = stimeformat.format(new Date((long) (time / 1000000))); String ns = Utils.formatNs(time, Resolution.NANOSEC); Utils.drawText(gc, stime + " " + ns, rect, true); } + @Override + public void drawAbsHeader(GC gc, long time, Rectangle rect) { + String header = stimeformatheader.format(new Date((long) (time / 1000000))); + int headerwidth = gc.stringExtent(header).x + 4; + if (headerwidth <= rect.width) { + rect.x += (rect.width - headerwidth); + Utils.drawText(gc, header, rect, true); + } + } + @Override public String hint() { return _hint; diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TmfTimeStatesCtrl.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TmfTimeStatesCtrl.java index 47ebf35ac7..3dcfe82ad7 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TmfTimeStatesCtrl.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TmfTimeStatesCtrl.java @@ -54,6 +54,8 @@ import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.ScrollBar; /** @@ -68,7 +70,7 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, public static final boolean DEFAULT_DRAW_THREAD_JOIN = true; public static final boolean DEFAULT_DRAW_THREAD_WAIT = true; public static final boolean DEFAULT_DRAW_THREAD_RELEASE = true; - public static final Integer H_SCROLLBAR_MAX = Integer.MAX_VALUE; + public static int H_SCROLLBAR_MAX = Integer.MAX_VALUE - 1; private final double zoomCoeff = 1.5; @@ -77,7 +79,7 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, private boolean _isDragCursor3 = false; private boolean _isWaitCursor = true; private boolean _mouseHover = false; - private int _itemHeightDefault = 18; + private int _itemHeightDefault = 19; private int _itemHeight = _itemHeightDefault; private int _topItem = 0; private int _dragState = 0; @@ -85,8 +87,6 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, private int _dragX0 = 0; private int _dragX = 0; private int _idealNameWidth = 0; - // TODO: 050409 - // private double _timeStep = 0.001; // private double _timeStep = 10000000; private long _time0bak; private long _time1bak; @@ -108,6 +108,8 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, private int _borderWidth = 0; private int _headerHeight = 0; + private Listener mouseScrollFilterListener; + public TmfTimeStatesCtrl(Composite parent, TraceColorScheme colors, TmfTimeAnalysisProvider rutilImp) { @@ -135,6 +137,13 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, if (scrollHor != null) { scrollHor.addSelectionListener(this); } + mouseScrollFilterListener = new Listener() { + // This filter is used to prevent scrolling of the view when the + // mouse wheel is used to zoom + public void handleEvent(Event event) { + event.doit = false; + } + }; _dragCursor3 = new Cursor(super.getDisplay(), SWT.CURSOR_SIZEWE); _WaitCursor = new Cursor(super.getDisplay(), SWT.CURSOR_WAIT); @@ -239,14 +248,11 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, long delta = timeMax - timeMin; int timePos = 0; - int thumb = 0; + int thumb = H_SCROLLBAR_MAX; if (delta != 0) { // Thumb size (page size) - thumb = Math - .max( - 1, - (int) (H_SCROLLBAR_MAX * ((double) (time1 - time0) / delta))); + thumb = Math.max(1, (int) (H_SCROLLBAR_MAX * ((double) (time1 - time0) / delta))); // At the beginning of visible window timePos = (int) (H_SCROLLBAR_MAX * ((double) (time0 - timeMin) / delta)); } @@ -378,12 +384,12 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, if (null == _timeProvider) return; ITmfTimeAnalysisEntry trace = getSelectedTrace(); - if (trace == _timeProvider) + if (trace == _timeProvider || trace == null) return; long selectedTime = _timeProvider.getSelectedTime(); long endTime = _timeProvider.getEndTime(); ITimeEvent nextEvent; - if (-1 == n && selectedTime >= endTime) + if (-1 == n && selectedTime > endTime) nextEvent = Utils.findEvent(trace, selectedTime, 0); else nextEvent = Utils.findEvent(trace, selectedTime, n); @@ -414,6 +420,38 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, selectTrace(-1); } + /** + * Zooming based on mouse cursor location with mouse scrolling + * + * @param zoomIn + */ + public void zoom(boolean zoomIn) { + int globalX = getDisplay().getCursorLocation().x; + Point p = toControl(globalX, 0); + int nameSpace = _timeProvider.getNameSpace(); + int timeSpace = _timeProvider.getTimeSpace(); + int xPos = Math.max(nameSpace, Math.min(nameSpace + timeSpace, p.x)); + long time0 = _timeProvider.getTime0(); + long time1 = _timeProvider.getTime1(); + long interval = time1 - time0; + if (interval == 0) { + interval = 1; + } // to allow getting out of single point interval + long newInterval; + if (zoomIn) { + newInterval = Math.max(Math.round((double) interval * 0.8), _timeProvider.getMinTimeInterval()); + } else { + newInterval = Math.round((double) interval * 1.25); + } + long center = time0 + Math.round(((double) (xPos - nameSpace) / timeSpace * interval)); + long newTime0 = center - Math.round((double) newInterval * (center - time0) / interval); + long newTime1 = newTime0 + newInterval; + _timeProvider.setStartFinishTime(newTime0, newTime1); + } + + /** + * zoom in using single click + */ public void zoomIn() { long _time0 = _timeProvider.getTime0(); long _time1 = _timeProvider.getTime1(); @@ -447,6 +485,9 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, _timeProvider.setStartFinishTimeNotify(time0, time1); } + /** + * zoom out using single click + */ public void zoomOut() { long _time0 = _timeProvider.getTime0(); long _time1 = _timeProvider.getTime1(); @@ -586,7 +627,7 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, int nameWidth = _timeProvider.getNameSpace(); x -= nameWidth; if (x >= 0 && size.x >= nameWidth) { - hitTime = time0 + ((time1 - time0) * x) / (size.x - nameWidth); + hitTime = time0 + (long) ((time1 - time0) * ((double) (x + 1) / (size.x - nameWidth - 1))) - 1; } return hitTime; } @@ -733,9 +774,10 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, return; int xr = bound.x + nameWidth; - double K = (double) (bound.width - xr) / (time1 - time0); + double pixelsPerNanoSec = (bound.width - xr <= 2) ? 0 + : (double) (bound.width - xr - 2) / (time1 - time0); // 2 pixels less to make sure end time is visible - int x0 = xr + (int) ((e.getTime() - time0) * K); + int x0 = xr + (int) ((e.getTime() - time0) * pixelsPerNanoSec); if (x0 < xr) return; @@ -855,16 +897,14 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, @Override void paint(Rectangle bound, PaintEvent e) { - // If no user preference defined for item height - if (_itemHeight == _itemHeightDefault) { - _itemHeight = getFontHeight() + 6; - } + GC gc = e.gc; + gc.setBackground(_colors.getColor(TraceColorScheme.BACKGROUND)); + drawBackground(gc, bound.x, bound.y, bound.width, bound.height); if (bound.width < 2 || bound.height < 2 || null == _timeProvider) return; _idealNameWidth = 0; - GC gc = e.gc; int nameWidth = _timeProvider.getNameSpace(); long time0 = _timeProvider.getTime0(); long time1 = _timeProvider.getTime1(); @@ -894,15 +934,6 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, if (drawTracesInteraction) drawTraceInteractions(bound, e.gc); - // fill free canvas area - _rect0.x = bound.x; - _rect0.y += _rect0.height; - _rect0.width = bound.width; - _rect0.height = bound.y + bound.height - _rect0.y; - if (_rect0.y < bound.y + bound.height) { - gc.setBackground(_colors.getColor(TraceColorScheme.BACKGROUND)); - gc.fillRectangle(_rect0); - } // draw drag line, no line if name space is 0. if (3 == _dragState) { gc.setForeground(_colors.getColor(TraceColorScheme.BLACK)); @@ -1024,7 +1055,8 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, Utils.init(_rect1, rect); boolean selected = item._selected; - double K = (double) rect.width / (time1 - time0); + double pixelsPerNanoSec = (rect.width <= 2) ? 0 + : (double) (rect.width - 2) / (time1 - time0); // 2 pixels less to make sure end time is visible boolean group = item instanceof GroupItem; if (group) { @@ -1043,8 +1075,8 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, ITimeEvent nextEvent = null; long currEventTime = currEvent.getTime(); long nextEventTime = currEventTime; - x0 = rect.x + (int) ((currEventTime - time0) * K); - int xEnd = rect.x + (int) ((time1 - time0) * K); + x0 = rect.x + (int) ((currEventTime - time0) * pixelsPerNanoSec); + int xEnd = rect.x + (int) ((time1 - time0) * pixelsPerNanoSec); int x1 = -1; int idx = 1; @@ -1068,7 +1100,7 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, nextEvent = null; nextEventTime = endTime; } - x1 = rect.x + (int) ((nextEventTime - time0) * K); + x1 = rect.x + (int) ((nextEventTime - time0) * pixelsPerNanoSec); if (x1 >= rect.x) { _rect1.x = x0 >= rect.x ? x0 : rect.x; _rect1.width = (x1 <= xEnd ? x1 : xEnd) - _rect1.x; @@ -1124,7 +1156,7 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, } // draw selected time - int x = rect.x + (int) ((selectedTime - time0) * K); + int x = rect.x + (int) ((selectedTime - time0) * pixelsPerNanoSec); if (x >= rect.x && x < rect.x + rect.width) { gc.setForeground(_colors.getColor(TraceColorScheme.SELECTED_TIME)); if (group) @@ -1163,7 +1195,8 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, Utils.init(_rect1, rect); boolean selected = item._selected; // K pixels per second - double K = (double) rect.width / (time1 - time0); + double pixelsPerNanoSec = (rect.width <= 2) ? 0 + : (double) (rect.width - 2) / (time1 - time0); // 2 pixels less to make sure end time is visible // Trace.debug("Value of K: " + K + " width:" + rect.width + " time0: " // + time0 + " time1:" + time1 + " endTime: " + endTime); @@ -1190,10 +1223,10 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, long currEventTime = currEvent.getTime(); long nextEventTime = currEventTime; // x0 - Points to the beginning of the event being drawn - double step = (double) ((currEventTime - time0) * K); + double step = (double) ((currEventTime - time0) * pixelsPerNanoSec); x0 = rect.x + step; // xEnd - Points to the end of the events rectangle - double xEnd = rect.x + (double) ((time1 - time0) * K); + double xEnd = rect.x + (double) ((time1 - time0) * pixelsPerNanoSec); double x1 = -1; int idx = 1; double xNext = 0; @@ -1241,7 +1274,7 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, // with space until next event _rect1.x += _rect1.width; x0 = x1; - xNext = rect.x + (double) ((nextEventTime - time0) * K); + xNext = rect.x + (double) ((nextEventTime - time0) * pixelsPerNanoSec); } // Fill space till next event fillSpace(rect, gc, selected, x0, xNext, xEnd); @@ -1250,7 +1283,7 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, currEvent = nextEvent; currEventTime = nextEventTime; // Move x0 to the beginning of next event - x0 = rect.x + (double) ((nextEventTime - time0) * K); + x0 = rect.x + (double) ((nextEventTime - time0) * pixelsPerNanoSec); // Trace.debug("rect.x: " + rect.x + " + " + // "(nextEvenTime: " // + nextEventTime + "- time0: " + time0 + ") * K: " @@ -1296,7 +1329,7 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, } // draw selected time - int x = rect.x + (int) ((selectedTime - time0) * K); + int x = rect.x + (int) ((selectedTime - time0) * pixelsPerNanoSec); if (x >= rect.x && x < rect.x + rect.width) { gc.setForeground(_colors.getColor(TraceColorScheme.SELECTED_TIME)); if (group) @@ -1337,7 +1370,8 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, Utils.init(_rect1, rect); boolean selected = item._selected; // K pixels per second - double K = (double) rect.width / (time1 - time0); + double pixelsPerNanoSec = (rect.width <= 2) ? 0 + : (double) (rect.width - 2) / (time1 - time0); // 2 pixels lesser to make sure end time is visible // Trace.debug("Value of K: " + K + " width:" + rect.width + " time0: " // + time0 + " time1:" + time1 + " endTime: " + endTime); @@ -1346,9 +1380,6 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, if (group) { // gc.setBackground(_colors.getBkColorGroup(selected, _isInFocus)); // gc.fillRectangle(rect); - // if (Trace.isDEBUG()) { - // Trace.debug("\n\t\t\tGroup: " + ((GroupItem) item)._name); - // } } else if (item instanceof TraceItem) { ITmfTimeAnalysisEntry trace = ((TraceItem) item)._trace; @@ -1356,12 +1387,19 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, List list = trace.getTraceEvents(); // Iterator it = list.iterator(); int count = list.size(); - ITimeEvent lastEvent = null; + // ITimeEvent lastEvent = null; // if (Trace.isDEBUG()) { // Trace.debug("\n\t\t\tTrace: " + trace.getName() // + utilImpl.getTraceClassName(trace)); // } // Trace.debug("count is: " + count); + // Drawing rectangle is smaller than reserved space + _rect1.y += 3; + _rect1.height -= 6; + + // Clean up to empty line to draw on top + int xEnd = rect.x + rect.width; + fillSpace(rect, gc, selected, _rect1.x, xEnd, xEnd); if (count > 0) { ITimeEvent currEvent = list.get(0); ITimeEvent nextEvent = null; @@ -1370,22 +1408,15 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, // initial value long nextEventTime = currEventTime; // x0 - Points to the beginning of the event being drawn - double step = (double) ((currEventTime - time0) * K); + double step = (double) ((currEventTime - time0) * pixelsPerNanoSec); x0 = rect.x + step; // xEnd - Points to the end of the events rectangle - double xEnd = rect.x + (double) ((time1 - time0) * K); double x1 = -1; int idx = 1; double xNext = 0; - // Drawing rectangle is smaller than reserved space - _rect1.y += 3; - _rect1.height -= 6; - - // Clean up to empty line to draw on top - fillSpace(rect, gc, selected, _rect1.x, xEnd, xEnd); // draw event states - while (x0 <= xEnd && null != currEvent) { + while (/* x0 <= xEnd &&*/ null != currEvent) { boolean stopped = false;// currEvent instanceof // refresh current event duration as the loop moves currEventDuration = currEvent.getDuration(); @@ -1406,14 +1437,15 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, } // Calculate position to next event - xNext = rect.x + (double) ((nextEventTime - time0) * K); + xNext = rect.x + (double) ((nextEventTime - time0) * pixelsPerNanoSec); // Calculate end position of current event if (currEventDuration < 0) { - x1 = rect.x + (double) ((nextEventTime - time0) * K); + x1 = rect.x + (double) ((nextEventTime - time0) * pixelsPerNanoSec); + } else if (currEventDuration == 0) { + x1 = x0; } else { - x1 = currEventDuration == 0 ? (x0 + 2) - : (x0 + (double) ((currEventDuration) * K)); + x1 = x0 + (double) ((currEventDuration) * pixelsPerNanoSec); } // If event end position x1 further away than start position @@ -1422,12 +1454,17 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, // Trace.debug("Next Event Pos: " + xNext // + " End Of Current at: " + x1 + " Event Duration: " // + currEventDuration); - x1 = x1 > xNext ? xNext : x1; + if (currEventDuration != 0) { + x1 = x1 > xNext ? xNext : x1; + } // if event end boundary is within time range if (x1 >= rect.x && x0 <= xEnd) { - // Fill with space until x0 - x0 = (double) (x0 >= rect.x ? x0 : rect.x); - _rect1.width = (int) ((x1 <= xEnd ? x1 : xEnd) - x0); + if (currEventDuration != 0) { + x0 = (double) (x0 >= rect.x ? x0 : rect.x); + } else { + x1 = x0 + 2; // make punctual events 2 pixels wide + } + _rect1.width = (int) Math.round((x1 <= xEnd ? x1 : xEnd) - x0); _rect1.x = (int) x0; boolean timeSelected = currEventTime <= selectedTime && selectedTime < nextEventTime; @@ -1444,13 +1481,13 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, } // Fill space till next event - fillSpace(rect, gc, selected, x0, xNext, xEnd); + // fillSpace(rect, gc, selected, x0, xNext, xEnd); - lastEvent = currEvent; + // lastEvent = currEvent; currEvent = nextEvent; currEventTime = nextEventTime; // Move x0 to the beginning of next event - x0 = rect.x + (double) ((nextEventTime - time0) * K); + x0 = rect.x + (double) ((nextEventTime - time0) * pixelsPerNanoSec); // Trace.debug("rect.x: " + rect.x + " + " + // "(nextEvenTime: " // + nextEventTime + "- time0: " + time0 + ") * K: " @@ -1458,26 +1495,6 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, } } - // fill space after last event - int xEnd = rect.x + rect.width; - if (x0 < xEnd) { - // Trace.debug("Space after last event, x0: " + x0 + ", xEnd: " - // + xEnd); - _rect1.x = (int) (x0 >= rect.x ? x0 : rect.x); - _rect1.width = xEnd - _rect1.x; - gc.setBackground(_colors - .getBkColor(selected, _isInFocus, false)); - gc.fillRectangle(_rect1); - // draw middle line - gc.setForeground(_colors.getColor(utilImpl - .getEventColorVal(lastEvent))); - int midy = _rect1.y + _rect1.height / 2; - int lw = gc.getLineWidth(); - gc.setLineWidth(2); - gc.drawLine(_rect1.x, midy, _rect1.x + _rect1.width, midy); - gc.setLineWidth(lw); - } - // draw focus area Utils.init(_rect1, rect); gc.setForeground(_colors.getBkColor(selected, _isInFocus, false)); @@ -1496,7 +1513,7 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, } // draw selected time - int x = rect.x + (int) ((selectedTime - time0) * K); + int x = rect.x + (int) ((double) (selectedTime - time0) * pixelsPerNanoSec); if (x >= rect.x && x < rect.x + rect.width) { gc.setForeground(_colors.getColor(TraceColorScheme.SELECTED_TIME)); if (group) @@ -1597,6 +1614,7 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, public void focusGained(FocusEvent e) { _isInFocus = true; redraw(); + getDisplay().addFilter(SWT.MouseWheel, mouseScrollFilterListener); } public void focusLost(FocusEvent e) { @@ -1606,6 +1624,7 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, _dragState = 0; } redraw(); + getDisplay().removeFilter(SWT.MouseWheel, mouseScrollFilterListener); } public boolean isInFocus() { @@ -1621,9 +1640,9 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, int x = e.x - nameWidth; if (x > 0 && size.x > nameWidth && _dragX != x) { _dragX = x; - double K = (double) (size.x - nameWidth) - / (_time1bak - _time0bak); - long timeDelta = (long) ((_dragX - _dragX0) / K); + double pixelsPerNanoSec = (size.x - nameWidth <= 2) ? 0 + : (double) (size.x - nameWidth - 2) / (_time1bak - _time0bak); // 2 pixels less to make sure end time is visible + long timeDelta = (long) ((pixelsPerNanoSec == 0) ? 0 : ((_dragX - _dragX0) / pixelsPerNanoSec)); long time1 = _time1bak - timeDelta; long maxTime = _timeProvider.getMaxTime(); if (time1 > maxTime) @@ -1643,6 +1662,10 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, if (_mouseHover != mouseHover) redraw(); _mouseHover = mouseHover; + // Make sure any time changes are notified to the application e.g. + // getting back from the horizontal scroll bar or zoomed using the + // mouse wheel + _timeProvider.setStartFinishTimeNotify(_timeProvider.getTime0(), _timeProvider.getTime1()); } updateCursor(e.x, e.y); } @@ -1751,6 +1774,8 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, } selectItem(idx, false); fireSelectionChanged(); + } else { + selectItem(idx, false); // clear selection } } } @@ -1768,7 +1793,7 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, } // Notify time provider to check the need for listener notification - _timeProvider.mouseUp(); + _timeProvider.setStartFinishTimeNotify(_timeProvider.getTime0(), _timeProvider.getTime1()); } public void controlMoved(ControlEvent e) { @@ -1788,7 +1813,7 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, _topItem = 0; redraw(); } else if (e.widget == getHorizontalBar() && null != _timeProvider) { - int startTime = getHorizontalBar().getSelection(); + int start = getHorizontalBar().getSelection(); long time0 = _timeProvider.getTime0(); long time1 = _timeProvider.getTime1(); long timeMin = _timeProvider.getMinTime(); @@ -1797,25 +1822,23 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, long range = time1 - time0; // _timeRangeFixed = true; - time0 = timeMin - + (long) ((double) ((startTime * delta) / H_SCROLLBAR_MAX)); + time0 = timeMin + (long) (delta * ((double) start / H_SCROLLBAR_MAX)); time1 = time0 + range; - // Trace.debug("\nstartTime:" + startTime + " time0:" + time0 - // + " time1:" + time1 + " Delta:" + delta); - _timeProvider.setStartFinishTimeNotify(time0, time1); + + // TODO: Follow-up with Bug 310310 + // In Linux SWT.DRAG is the only value received + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=310310 + if (e.detail == SWT.DRAG) { + _timeProvider.setStartFinishTime(time0, time1); + } else { + _timeProvider.setStartFinishTimeNotify(time0, time1); + } } } public void mouseEnter(MouseEvent e) { } - /* - * (non-Javadoc) - * - * @see - * org.eclipse.swt.events.MouseTrackListener#mouseExit(org.eclipse.swt.events - * .MouseEvent) - */ public void mouseExit(MouseEvent e) { if (_mouseHover) { _mouseHover = false; @@ -1827,10 +1850,12 @@ public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, } public void mouseScrolled(MouseEvent e) { + if (!_isInFocus) + return; if (e.count > 0) { - zoomIn(); + zoom(true); } else if (e.count < 0) { - zoomOut(); + zoom(false); } } diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TmfTimeTipHandler.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TmfTimeTipHandler.java index bdd38c1416..eda2d7992b 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TmfTimeTipHandler.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TmfTimeTipHandler.java @@ -17,8 +17,8 @@ package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets; import java.util.Iterator; import java.util.Map; -import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeAnalysisProvider; import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.Messages; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeAnalysisProvider; import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITimeAnalysisViewer.TimeFormat; import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent; import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; @@ -131,19 +131,20 @@ public class TmfTimeTipHandler { addItem(message, eventAddOns.get(message)); } - // start time - long startTime = threadEvent == null ? thrd.getStartTime() - : threadEvent.getTime(); - - long duration = threadEvent == null ? -1 : threadEvent - .getDuration(); - - if (duration < 0 && threadEvent != null - && nextEvent != null) { - long stopTime = nextEvent.getTime(); - duration = stopTime - startTime; + long eventStartTime = -1; + long eventDuration = -1; + long eventEndTime = -1; + + if (threadEvent != null) { + eventStartTime = threadEvent.getTime(); + eventDuration = threadEvent.getDuration(); + if (eventDuration < 0 && nextEvent != null) { + eventEndTime = nextEvent.getTime(); + eventDuration = eventEndTime - eventStartTime; + } else { + eventEndTime = eventStartTime + eventDuration; + } } - long eventEndtime = startTime + duration; // TODO: Check if we need "format" // TimeFormat format = TimeFormat.RELATIVE; @@ -152,19 +153,44 @@ public class TmfTimeTipHandler { // format = TimeFormat.ABSOLUTE; // Absolute format // // (calendar) // Add Date - addItem(Messages._TRACE_DATE, Utils - .formatDate(startTime)); + addItem(Messages._TRACE_DATE, eventStartTime > -1 ? + Utils.formatDate(eventStartTime) + : "?"); + if (eventDuration > 0) { + addItem(Messages._TRACE_START_TIME, eventStartTime > -1 ? + Utils.formatTime(eventStartTime, TimeFormat.ABSOLUTE, res) + : "?"); + + addItem(Messages._TRACE_STOP_TIME, eventEndTime > -1 ? + Utils.formatTime(eventEndTime, TimeFormat.ABSOLUTE, res) + : "?"); + } else { + addItem(Messages._TRACE_EVENT_TIME, eventStartTime > -1 ? + Utils.formatTime(eventStartTime, TimeFormat.ABSOLUTE, res) + : "?"); + } + } else { + if (eventDuration > 0) { + addItem(Messages._TRACE_START_TIME, eventStartTime > -1 ? + Utils.formatTime(eventStartTime, TimeFormat.RELATIVE, res) + : "?"); + + addItem(Messages._TRACE_STOP_TIME, eventEndTime > -1 ? + Utils.formatTime(eventEndTime, TimeFormat.RELATIVE, res) + : "?"); + } else { + addItem(Messages._TRACE_EVENT_TIME, eventStartTime > -1 ? + Utils.formatTime(eventStartTime, TimeFormat.RELATIVE, res) + : "?"); + } } - addItem(Messages._TRACE_START_TIME, Utils.formatTime( - startTime, TimeFormat.RELATIVE, res)); - - addItem(Messages._TRACE_STOP_TIME, Utils.formatTime( - eventEndtime, TimeFormat.RELATIVE, res)); - // Duration in relative format in any case - addItem(Messages._DURATION, duration > -1 ? Utils - .formatTime(duration, TimeFormat.RELATIVE, res) - : "?"); + if (eventDuration > 0) { + // Duration in relative format in any case + addItem(Messages._DURATION, eventDuration > -1 ? + Utils.formatTime(eventDuration, TimeFormat.RELATIVE, res) + : "?"); + } } else if (item instanceof GroupItem) { addItem(Messages._TRACE_GROUP_NAME, item.toString()); diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TraceColorScheme.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TraceColorScheme.java index 962767fd76..32c533ceb7 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TraceColorScheme.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TraceColorScheme.java @@ -130,7 +130,9 @@ public class TraceColorScheme { static public final int GR_FOREGROUND_SEL_NOFOCUS = 76; static public final int LIGHT_LINE = 77; - static public final int BACKGROUND_NAME = 78; + static public final int BACKGROUND_NAME = 78; + static public final int BACKGROUND_NAME_SEL = 79; + static public final int BACKGROUND_NAME_SEL_NOFOCUS = 80; // Interraction's colors static public final int TI_START_THREAD = BLACK; @@ -205,8 +207,7 @@ public class TraceColorScheme { // new RGB(100, 100, 100), // UNKNOWN new RGB(174, 200, 124), // RUNNING - new Mix(new SysCol(SWT.COLOR_BLUE), new SysCol(SWT.COLOR_GRAY), 1, - 3), // SLEEPING + new Mix(new SysCol(SWT.COLOR_BLUE), new SysCol(SWT.COLOR_GRAY), 1, 3), // SLEEPING new RGB(210, 150, 60), // WAITING new RGB(242, 225, 168), // BLOCKED new Mix(new SysCol(SWT.COLOR_RED), new SysCol(SWT.COLOR_GRAY), 1, 3), // DEADLOCK @@ -243,8 +244,8 @@ public class TraceColorScheme { new SysCol(SWT.COLOR_LIST_BACKGROUND), // BACKGROUND new SysCol(SWT.COLOR_LIST_FOREGROUND), // FOREGROUND - new SysCol(SWT.COLOR_LIST_SELECTION), // BACKGROUND_SEL - new SysCol(SWT.COLOR_LIST_SELECTION_TEXT), // FOREGROUND_SEL + new RGB(232, 242, 254), // BACKGROUND_SEL + new SysCol(SWT.COLOR_LIST_FOREGROUND), // FOREGROUND_SEL new SysCol(SWT.COLOR_WIDGET_BACKGROUND), // BACKGROUND_SEL_NOFOCUS new SysCol(SWT.COLOR_WIDGET_FOREGROUND), // FOREGROUND_SEL_NOFOCUS new SysCol(SWT.COLOR_WIDGET_BACKGROUND), // TOOL_BACKGROUND @@ -299,8 +300,10 @@ public class TraceColorScheme { new Mix(new SysCol(SWT.COLOR_GRAY), new SysCol( SWT.COLOR_LIST_BACKGROUND), 1, 3), // LIGHT_LINE - new Mix(new SysCol(SWT.COLOR_GRAY), new SysCol( - SWT.COLOR_LIST_BACKGROUND), 1, 6), // BACKGROUND_NAME + + new Mix(new SysCol(SWT.COLOR_GRAY), new SysCol(SWT.COLOR_LIST_BACKGROUND), 1, 6), // BACKGROUND_NAME + new Mix(new SysCol(SWT.COLOR_GRAY), new RGB(232, 242, 254), 1, 6), // BACKGROUND_NAME_SEL + new Mix(new SysCol(SWT.COLOR_GRAY), new SysCol(SWT.COLOR_WIDGET_BACKGROUND), 1, 6), // BACKGROUND_NAME_SEL_NOFOCUS }; private Color _colors[]; @@ -330,13 +333,19 @@ public class TraceColorScheme { } public Color getBkColor(boolean selected, boolean focused, boolean name) { - if (selected && focused) - return getColor(BACKGROUND_SEL); - if (selected) - return getColor(BACKGROUND_SEL_NOFOCUS); - if (name) - return getColor(BACKGROUND_NAME); - return getColor(BACKGROUND); + if (name) { + if (selected && focused) + return getColor(BACKGROUND_NAME_SEL); + if (selected) + return getColor(BACKGROUND_NAME_SEL_NOFOCUS); + return getColor(BACKGROUND_NAME); + } else { + if (selected && focused) + return getColor(BACKGROUND_SEL); + if (selected) + return getColor(BACKGROUND_SEL_NOFOCUS); + return getColor(BACKGROUND); + } } public Color getFgColor(boolean selected, boolean focused) { diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/Utils.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/Utils.java index 730a3dc0f2..80680e32fd 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/Utils.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/Utils.java @@ -19,12 +19,13 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; import java.util.List; +import java.util.TimeZone; import java.util.Vector; import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITimeAnalysisViewer.TimeFormat; -import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.TimeEvent; import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent; import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.TimeEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.GC; @@ -47,8 +48,12 @@ public class Utils { SECONDS, MILLISEC, MICROSEC, NANOSEC }; - static private SimpleDateFormat stimeformat = new SimpleDateFormat("HH:mm:ss"); - static private SimpleDateFormat sdateformat = new SimpleDateFormat("yyyy.MM.dd"); + static private final SimpleDateFormat stimeformat = new SimpleDateFormat("HH:mm:ss"); + static private final SimpleDateFormat sdateformat = new SimpleDateFormat("yyyy-MM-dd"); + static { + stimeformat.setTimeZone(TimeZone.getTimeZone("GMT")); + sdateformat.setTimeZone(TimeZone.getTimeZone("GMT")); + } // static private String _externalPlugin[] = { "org.eclipse.debug.ui", // "org.eclipse.debug.ui", "org.eclipse.debug.ui", @@ -335,64 +340,49 @@ public class Utils { * @param n * @return */ - static ITimeEvent findEvent(ITmfTimeAnalysisEntry thread, long time, int n) { - if (null == thread) - return null; - List list = thread.getTraceEvents(); - Iterator it = list.iterator(); - ITimeEvent event = null; - ITimeEvent prevEvent = null; - ITimeEvent nextEvent = null; - if (it.hasNext()) { - event = (ITimeEvent) it.next(); - long currStartTime = event.getTime(); - long currEndTime = currStartTime + event.getDuration(); - - if (time < currStartTime) { - if (1 != n) - event = null; - return event; - } - while (it.hasNext()) { - currStartTime = event.getTime(); - currEndTime = currStartTime + event.getDuration(); - nextEvent = (ITimeEvent) it.next(); - - long nextEventTime = nextEvent.getTime(); - currEndTime = currEndTime >= nextEventTime ? (nextEventTime - 1) - : currEndTime; - -// Trace.debug("currStartTime: " + currStartTime -// + " currEndTime: " + currEndTime + " nextEventTime: " -// + nextEventTime + " time: " + time); - if (currStartTime <= time && time <= currEndTime) { - if (1 == n) - event = nextEvent; - else if (-1 == n) - event = prevEvent; - return event; - } - - if (time > currEndTime && time < nextEventTime) { - //Located in a non Event area - if (2 == n || -1 == n) { - return event; - } else if (1 == n) { - return nextEvent; - } - return null; - } - - prevEvent = event; - event = nextEvent; - } - } - if (1 == n) - event = null; - else if (-1 == n) - event = prevEvent; - return event; - } + static ITimeEvent findEvent(ITmfTimeAnalysisEntry thread, long time, int n) { + if (null == thread) + return null; + List list = thread.getTraceEvents(); + Iterator it = list.iterator(); + ITimeEvent nextEvent = null; + ITimeEvent currEvent = null; + ITimeEvent prevEvent = null; + + while (it.hasNext()) { + nextEvent = (ITimeEvent) it.next(); + long nextStartTime = nextEvent.getTime(); + + if (nextStartTime > time) { + break; + } + + if (currEvent == null || currEvent.getTime() != nextStartTime) { + prevEvent = currEvent; + currEvent = nextEvent; + } + } + + if (n == -1) { //previous + if (currEvent != null && currEvent.getTime() + currEvent.getDuration() >= time) { + return prevEvent; + } else { + return currEvent; + } + } else if (n == 0) { //current + if (currEvent != null && currEvent.getTime() + currEvent.getDuration() >= time) { + return currEvent; + } else { + return null; + } + } else if (n == 1) { //next + return nextEvent; + } else if (n == 2) { //current or previous when in empty space + return currEvent; + } + + return null; + } // static public TRCPackage getPackage(Object element) { // if (element instanceof TRCPackage) -- 2.34.1