ss: Move plugins to Trace Compass namespace
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / views / histogram / Histogram.java
index 41868fbff238164d2a2b9ab7ab4449cfe838ff6a..de0f720aeb4692824a3b2779587f14af31a8596b 100644 (file)
@@ -11,6 +11,7 @@
  *   Bernd Hufmann - Changed to updated histogram data model
  *   Francois Chouinard - Reformat histogram labels on format change
  *   Patrick Tasse - Support selection range
+ *   Xavier Raynaud - Support multi-trace coloring
  *******************************************************************************/
 
 package org.eclipse.linuxtools.tmf.ui.views.histogram;
@@ -27,9 +28,8 @@ import org.eclipse.osgi.util.NLS;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.ControlEvent;
 import org.eclipse.swt.events.ControlListener;
-import org.eclipse.swt.events.FocusAdapter;
-import org.eclipse.swt.events.FocusEvent;
-import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
 import org.eclipse.swt.events.KeyEvent;
 import org.eclipse.swt.events.KeyListener;
 import org.eclipse.swt.events.MouseEvent;
@@ -51,7 +51,6 @@ import org.eclipse.swt.widgets.Canvas;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Text;
 
 /**
  * Re-usable histogram widget.
@@ -97,14 +96,40 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
     // ------------------------------------------------------------------------
 
     // Histogram colors
+
+    // System colors, they do not need to be disposed
     private final Color fBackgroundColor = Display.getCurrent().getSystemColor(SWT.COLOR_WHITE);
     private final Color fSelectionForegroundColor = Display.getCurrent().getSystemColor(SWT.COLOR_BLUE);
     private final Color fSelectionBackgroundColor = Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
     private final Color fLastEventColor = Display.getCurrent().getSystemColor(SWT.COLOR_DARK_RED);
-    private final Color fHistoBarColor = new Color(Display.getDefault(), 74, 112, 139);
-    private final Color fLostEventColor = new Color(Display.getCurrent(), 208, 62, 120);
-    private final Color fFillColor = Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
+
+    // Application colors, they need to be disposed
+    private final Color[] fHistoBarColors = new Color[] {new Color(Display.getDefault(), 90, 90, 255), // blue
+            new Color(Display.getDefault(), 0, 240, 0), // green
+            new Color(Display.getDefault(), 255, 0, 0), // red
+            new Color(Display.getDefault(), 0, 255, 255), // cyan
+            new Color(Display.getDefault(), 255, 80, 255), // magenta
+            new Color(Display.getDefault(), 200, 200, 0), // yellow
+            new Color(Display.getDefault(), 200, 150, 0), // brown
+            new Color(Display.getDefault(), 150, 255, 150), // light green
+            new Color(Display.getDefault(), 200, 80, 80), // dark red
+            new Color(Display.getDefault(), 30, 150, 150), // dark cyan
+            new Color(Display.getDefault(), 200, 200, 255), // light blue
+            new Color(Display.getDefault(), 0, 120, 0), // dark green
+            new Color(Display.getDefault(), 255, 150, 150), // lighter red
+            new Color(Display.getDefault(), 140, 80, 140), // dark magenta
+            new Color(Display.getDefault(), 150, 100, 50), // brown
+            new Color(Display.getDefault(), 255, 80, 80), // light red
+            new Color(Display.getDefault(), 200, 200, 200), // light grey
+            new Color(Display.getDefault(), 255, 200, 80), // orange
+            new Color(Display.getDefault(), 255, 255, 80), // pale yellow
+            new Color(Display.getDefault(), 255, 200, 200), // pale red
+            new Color(Display.getDefault(), 255, 200, 255), // pale magenta
+            new Color(Display.getDefault(), 255, 255, 200), // pale pale yellow
+            new Color(Display.getDefault(), 200, 255, 255), // pale pale blue
+    };
     private final Color fTimeRangeColor = new Color(Display.getCurrent(), 255, 128, 0);
+    private final Color fLostEventColor = new Color(Display.getCurrent(), 208, 62, 120);
 
     // Drag states
     /**
@@ -141,10 +166,10 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
     private Font fFont;
 
     // Histogram text fields
-    private Text fMaxNbEventsText;
-    private Text fMinNbEventsText;
-    private Text fTimeRangeStartText;
-    private Text fTimeRangeEndText;
+    private Label fMaxNbEventsLabel;
+    private Label fMinNbEventsLabel;
+    private Label fTimeRangeStartLabel;
+    private Label fTimeRangeEndLabel;
 
     /**
      * Histogram drawing area
@@ -197,6 +222,12 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
      */
     private int fOffset = 0;
 
+    /**
+     * show the traces or not
+     * @since 3.0
+     */
+    static boolean showTraces = true;
+
     // ------------------------------------------------------------------------
     // Construction
     // ------------------------------------------------------------------------
@@ -230,16 +261,18 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
      */
     public void dispose() {
         TmfSignalManager.deregister(this);
-
-        fHistoBarColor.dispose();
-        fLastEventColor.dispose();
+        fLostEventColor.dispose();
+        for (Color c : fHistoBarColors) {
+            c.dispose();
+        }
         fTimeRangeColor.dispose();
+        fFont.dispose();
         fDataModel.removeHistogramListener(this);
+        fDataModel.dispose();
     }
 
     private Composite createWidget(final Composite parent) {
 
-        final Color labelColor = parent.getBackground();
         fFont = adjustFont(parent);
 
         final int initalWidth = 10;
@@ -272,12 +305,10 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
         gridData = new GridData();
         gridData.horizontalAlignment = SWT.RIGHT;
         gridData.verticalAlignment = SWT.TOP;
-        fMaxNbEventsText = new Text(composite, SWT.READ_ONLY | SWT.RIGHT);
-        fMaxNbEventsText.setFont(fFont);
-        fMaxNbEventsText.setBackground(labelColor);
-        fMaxNbEventsText.setEditable(false);
-        fMaxNbEventsText.setText("0"); //$NON-NLS-1$
-        fMaxNbEventsText.setLayoutData(gridData);
+        fMaxNbEventsLabel = new Label(composite, SWT.RIGHT);
+        fMaxNbEventsLabel.setFont(fFont);
+        fMaxNbEventsLabel.setText("0"); //$NON-NLS-1$
+        fMaxNbEventsLabel.setLayoutData(gridData);
 
         // Histogram itself
         Composite canvasComposite = new Composite(composite, SWT.BORDER);
@@ -293,17 +324,24 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
         canvasComposite.setLayoutData(gridData);
         canvasComposite.setLayout(new FillLayout());
         fCanvas = new Canvas(canvasComposite, SWT.DOUBLE_BUFFERED);
+        fCanvas.addDisposeListener(new DisposeListener() {
+            @Override
+            public void widgetDisposed(DisposeEvent e) {
+                Object image = fCanvas.getData(IMAGE_KEY);
+                if (image instanceof Image) {
+                    ((Image) image).dispose();
+                }
+            }
+        });
 
         // Y-axis min event (always 0...)
         gridData = new GridData();
         gridData.horizontalAlignment = SWT.RIGHT;
         gridData.verticalAlignment = SWT.BOTTOM;
-        fMinNbEventsText = new Text(composite, SWT.READ_ONLY | SWT.RIGHT);
-        fMinNbEventsText.setFont(fFont);
-        fMinNbEventsText.setBackground(labelColor);
-        fMinNbEventsText.setEditable(false);
-        fMinNbEventsText.setText("0"); //$NON-NLS-1$
-        fMinNbEventsText.setLayoutData(gridData);
+        fMinNbEventsLabel = new Label(composite, SWT.RIGHT);
+        fMinNbEventsLabel.setFont(fFont);
+        fMinNbEventsLabel.setText("0"); //$NON-NLS-1$
+        fMinNbEventsLabel.setLayoutData(gridData);
 
         // Dummy cell
         gridData = new GridData(initalWidth, SWT.DEFAULT);
@@ -316,30 +354,17 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
         gridData = new GridData();
         gridData.horizontalAlignment = SWT.LEFT;
         gridData.verticalAlignment = SWT.BOTTOM;
-        fTimeRangeStartText = new Text(composite, SWT.READ_ONLY);
-        fTimeRangeStartText.setFont(fFont);
-        fTimeRangeStartText.setBackground(labelColor);
-        fTimeRangeStartText.setLayoutData(gridData);
+        fTimeRangeStartLabel = new Label(composite, SWT.NONE);
+        fTimeRangeStartLabel.setFont(fFont);
+        fTimeRangeStartLabel.setLayoutData(gridData);
 
         // Window range end time
         gridData = new GridData();
         gridData.horizontalAlignment = SWT.RIGHT;
         gridData.verticalAlignment = SWT.BOTTOM;
-        fTimeRangeEndText = new Text(composite, SWT.READ_ONLY);
-        fTimeRangeEndText.setFont(fFont);
-        fTimeRangeEndText.setBackground(labelColor);
-        fTimeRangeEndText.setLayoutData(gridData);
-
-        FocusListener listener = new FocusAdapter() {
-            @Override
-            public void focusGained(FocusEvent e) {
-                fCanvas.setFocus();
-            }
-        };
-        fMaxNbEventsText.addFocusListener(listener);
-        fMinNbEventsText.addFocusListener(listener);
-        fTimeRangeStartText.addFocusListener(listener);
-        fTimeRangeEndText.addFocusListener(listener);
+        fTimeRangeEndLabel = new Label(composite, SWT.NONE);
+        fTimeRangeEndLabel.setFont(fFont);
+        fTimeRangeEndLabel.setLayoutData(gridData);
 
         return composite;
     }
@@ -389,13 +414,45 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
     }
 
     /**
-     * Returns the text control for the maximum of events in one bar
+     * Set the max number events to be displayed
      *
-     * @return the text control
-     * @since 2.2
+     * @param maxNbEvents
+     *            the maximum number of events
+     */
+    void setMaxNbEvents(long maxNbEvents) {
+        fMaxNbEventsLabel.setText(Long.toString(maxNbEvents));
+        fMaxNbEventsLabel.getParent().layout();
+        fCanvas.redraw();
+    }
+
+    /**
+     * Return <code>true</code> if the traces must be displayed in the histogram,
+     * <code>false</code> otherwise.
+     * @return whether the traces should be displayed
+     * @since 3.0
+     */
+    public boolean showTraces() {
+        return showTraces && fDataModel.getNbTraces() < getMaxNbTraces();
+    }
+
+    /**
+     * Returns the maximum number of traces the histogram can display with separate colors.
+     * If there is more traces, histogram will use only one color to display them.
+     * @return the maximum number of traces the histogram can display.
+     * @since 3.0
+     */
+    public int getMaxNbTraces() {
+        return fHistoBarColors.length;
+    }
+
+    /**
+     * Returns the color used to display the trace at the given index.
+     * @param traceIndex a trace index
+     * @return a {@link Color}
+     * @since 3.0
      */
-    public Text getMaxNbEventsText() {
-        return fMaxNbEventsText;
+    public Color getTraceColor(int traceIndex) {
+        return fHistoBarColors[traceIndex % fHistoBarColors.length];
     }
 
     // ------------------------------------------------------------------------
@@ -427,16 +484,6 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
         }
     }
 
-    /**
-     * Increase the histogram bucket corresponding to [timestamp]
-     *
-     * @param eventCount The new event count
-     * @param timestamp The latest timestamp
-     */
-    public void countEvent(final long eventCount, final long timestamp) {
-        fDataModel.countEvent(eventCount, timestamp);
-    }
-
     /**
      * Sets the current selection time range and refresh the display
      *
@@ -501,7 +548,7 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
 
         case SWT.HOME:
             index = 0;
-            while (index < fScaledData.fLastBucket && fScaledData.fData[index] == 0) {
+            while (index < fScaledData.fLastBucket && fScaledData.fData[index].isEmpty()) {
                 index++;
             }
             if (index < fScaledData.fLastBucket) {
@@ -511,7 +558,7 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
 
         case SWT.ARROW_RIGHT:
             index = Math.max(0, fScaledData.fSelectionBeginBucket + 1);
-            while (index < fScaledData.fWidth && fScaledData.fData[index] == 0) {
+            while (index < fScaledData.fWidth && fScaledData.fData[index].isEmpty()) {
                 index++;
             }
             if (index < fScaledData.fLastBucket) {
@@ -521,7 +568,7 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
 
         case SWT.END:
             index = fScaledData.fLastBucket;
-            while (index >= 0 && fScaledData.fData[index] == 0) {
+            while (index >= 0 && fScaledData.fData[index].isEmpty()) {
                 index--;
             }
             if (index >= 0) {
@@ -531,7 +578,7 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
 
         case SWT.ARROW_LEFT:
             index = Math.min(fScaledData.fLastBucket - 1, fScaledData.fSelectionBeginBucket - 1);
-            while (index >= 0 && fScaledData.fData[index] == 0) {
+            while (index >= 0 && fScaledData.fData[index].isEmpty()) {
                 index--;
             }
             if (index >= 0) {
@@ -573,11 +620,11 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
                                 // Display histogram and update X-,Y-axis labels
                                 updateRangeTextControls();
                                 long maxNbEvents = HistogramScaledData.hideLostEvents ? fScaledData.fMaxValue : fScaledData.fMaxCombinedValue;
-                                fMaxNbEventsText.setText(Long.toString(maxNbEvents));
+                                fMaxNbEventsLabel.setText(Long.toString(maxNbEvents));
                                 // The Y-axis area might need to be re-sized
-                                GridData gd = (GridData) fMaxNbEventsText.getLayoutData();
-                                gd.widthHint = Math.max(gd.widthHint, fMaxNbEventsText.computeSize(SWT.DEFAULT, SWT.DEFAULT).x);
-                                fMaxNbEventsText.getParent().layout();
+                                GridData gd = (GridData) fMaxNbEventsLabel.getLayoutData();
+                                gd.widthHint = Math.max(gd.widthHint, fMaxNbEventsLabel.computeSize(SWT.DEFAULT, SWT.DEFAULT).x);
+                                fMaxNbEventsLabel.getParent().layout();
                             }
                         }
                     }
@@ -604,6 +651,24 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
         fCanvas.removeMouseWheelListener(listener);
     }
 
+    /**
+     * Add a key listener to the histogram
+     * @param listener the key listener
+     * @since 3.1
+     */
+    public void addKeyListener(KeyListener listener) {
+        fCanvas.addKeyListener(listener);
+    }
+
+    /**
+     * Remove a key listener from the histogram
+     * @param listener the key listener
+     * @since 3.1
+     */
+    public void removeKeyListener(KeyListener listener) {
+        fCanvas.removeKeyListener(listener);
+    }
+
     // ------------------------------------------------------------------------
     // Helper functions
     // ------------------------------------------------------------------------
@@ -622,11 +687,11 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
      */
     private void updateRangeTextControls() {
         if (fDataModel.getStartTime() < fDataModel.getEndTime()) {
-            fTimeRangeStartText.setText(TmfTimestampFormat.getDefaulTimeFormat().format(fDataModel.getStartTime()));
-            fTimeRangeEndText.setText(TmfTimestampFormat.getDefaulTimeFormat().format(fDataModel.getEndTime()));
+            fTimeRangeStartLabel.setText(TmfTimestampFormat.getDefaulTimeFormat().format(fDataModel.getStartTime()));
+            fTimeRangeEndLabel.setText(TmfTimestampFormat.getDefaulTimeFormat().format(fDataModel.getEndTime()));
         } else {
-            fTimeRangeStartText.setText(""); //$NON-NLS-1$
-            fTimeRangeEndText.setText(""); //$NON-NLS-1$
+            fTimeRangeStartLabel.setText(""); //$NON-NLS-1$
+            fTimeRangeEndLabel.setText(""); //$NON-NLS-1$
         }
     }
 
@@ -653,6 +718,9 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
         // Retrieve image; re-create only if necessary
         Image image = (Image) fCanvas.getData(IMAGE_KEY);
         if (image == null || image.getBounds().width != canvasWidth || image.getBounds().height != canvasHeight) {
+            if (image != null) {
+                image.dispose();
+            }
             image = new Image(event.display, canvasWidth, canvasHeight);
             fCanvas.setData(IMAGE_KEY, image);
         }
@@ -684,8 +752,11 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
             // Draw the histogram bars
             final int limit = width < scaledData.fWidth ? width : scaledData.fWidth;
             double factor = HistogramScaledData.hideLostEvents ? scaledData.fScalingFactor : scaledData.fScalingFactorCombined;
+            final boolean showTracesColors = showTraces();
             for (int i = 0; i < limit; i++) {
-                final int value = (int) Math.ceil(scaledData.fData[i] * factor);
+                HistogramBucket hb = scaledData.fData[i];
+                int totalNbEvents = hb.getNbEvents();
+                int value = (int) Math.ceil(totalNbEvents * factor);
                 int x = i + fOffset;
 
                 // in Linux, the last pixel in a line is not drawn,
@@ -701,8 +772,24 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
                 }
 
                 // then draw normal events second, to overwrite that extra pixel
-                imageGC.setForeground(fHistoBarColor);
-                imageGC.drawLine(x, height - value, x, height);
+                if (!hb.isEmpty()) {
+                    if (showTracesColors) {
+                        for (int traceIndex = 0; traceIndex < hb.getNbTraces(); traceIndex++) {
+                            int nbEventsForTrace = hb.getNbEvent(traceIndex);
+                            if (nbEventsForTrace > 0) {
+                                Color c = fHistoBarColors[traceIndex % fHistoBarColors.length];
+                                imageGC.setForeground(c);
+                                imageGC.drawLine(x, height - value, x, height);
+                                totalNbEvents -= nbEventsForTrace;
+                                value = (int) Math.ceil(totalNbEvents * scaledData.fScalingFactor);
+                            }
+                        }
+                    } else {
+                        Color c = fHistoBarColors[0];
+                        imageGC.setForeground(c);
+                        imageGC.drawLine(x, height - value, x, height);
+                    }
+                }
             }
 
             // Draw the selection bars
@@ -732,7 +819,7 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
             drawDelimiter(imageGC, fLastEventColor, height, delimiterIndex);
 
             // Fill the area to the right of delimiter with background color
-            imageGC.setBackground(fFillColor);
+            imageGC.setBackground(fComposite.getBackground());
             imageGC.fillRectangle(delimiterIndex + 1, 0, width - (delimiterIndex + 1), height);
 
         } catch (final Exception e) {
@@ -900,7 +987,7 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
             startTime = 0;
         }
         final long endTime = fScaledData.getBucketEndTime(index);
-        final int nbEvents = (index >= 0) ? fScaledData.fData[index] : 0;
+        final int nbEvents = (index >= 0) ? fScaledData.fData[index].getNbEvents() : 0;
         final String newLine = System.getProperty("line.separator"); //$NON-NLS-1$
         final StringBuffer buffer = new StringBuffer();
         int selectionBeginBucket = Math.min(fScaledData.fSelectionBeginBucket, fScaledData.fSelectionEndBucket);
This page took 0.030589 seconds and 5 git commands to generate.