+ * The TimeGraphViewerExtension is used to set appropriate values and to
+ * override methods that could be called directly by the user and that must
+ * be handled by the time graph combo.
+ */
+ private class TimeGraphViewerExtension extends TimeGraphViewer {
+
+ private TimeGraphViewerExtension(Composite parent, int style, Tree tree) {
+ super(parent, style);
+ setItemHeight(TimeGraphCombo.this.getItemHeight(tree, true));
+ setHeaderHeight(tree.getHeaderHeight());
+ setBorderWidth(tree.getBorderWidth());
+ setNameWidthPref(0);
+ }
+
+ @Override
+ public ShowFilterDialogAction getShowFilterDialogAction() {
+ return TimeGraphCombo.this.getShowFilterDialogAction();
+ }
+
+ @Override
+ protected TimeGraphControl createTimeGraphControl(Composite composite, TimeGraphColorScheme colors) {
+ return new TimeGraphControl(composite, colors) {
+ @Override
+ public void verticalZoom(boolean zoomIn) {
+ TimeGraphCombo.this.verticalZoom(zoomIn);
+ }
+
+ @Override
+ public void resetVerticalZoom() {
+ TimeGraphCombo.this.resetVerticalZoom();
+ }
+
+ @Override
+ public void setElementPosition(ITimeGraphEntry entry, int y) {
+ /*
+ * Queue the update to make sure the time graph combo has
+ * finished updating the item heights.
+ */
+ getDisplay().asyncExec(() -> {
+ if (isDisposed()) {
+ return;
+ }
+ super.setElementPosition(entry, y);
+ alignTreeItems(false);
+ });
+ }
+ };
+ }
+
+ private class TimeGraphMarkerAxisExtension extends TimeGraphMarkerAxis {
+ private int fMargin = 0;
+
+ public TimeGraphMarkerAxisExtension(Composite parent, @NonNull TimeGraphColorScheme colorScheme, @NonNull ITimeDataProvider timeProvider) {
+ super(parent, colorScheme, timeProvider);
+ }
+
+ @Override
+ public Point computeSize(int wHint, int hHint, boolean changed) {
+ Point size = super.computeSize(wHint, hHint, changed);
+ if (size.y > 0) {
+ size.y += fMargin;
+ }
+ return size;
+ }
+
+ @Override
+ public void redraw() {
+ super.redraw();
+ fTreeViewer.getControl().redraw();
+ }
+
+ @Override
+ protected void drawMarkerAxis(Rectangle bounds, int nameSpace, GC gc) {
+ super.drawMarkerAxis(bounds, nameSpace, gc);
+ }
+
+ private Rectangle getAxisBounds() {
+ Tree tree = fTreeViewer.getTree();
+ Rectangle axisBounds = getBounds();
+ Rectangle treeClientArea = tree.getClientArea();
+ if (axisBounds.isEmpty()) {
+ treeClientArea.y += treeClientArea.height;
+ treeClientArea.height = 0;
+ return treeClientArea;
+ }
+ Composite axisParent = getParent();
+ Point axisDisplayCoordinates = axisParent.toDisplay(axisBounds.x, axisBounds.y);
+ Point axisTreeCoordinates = tree.toControl(axisDisplayCoordinates);
+ int height = treeClientArea.y + treeClientArea.height - axisTreeCoordinates.y;
+ int margin = Math.max(0, axisBounds.height - height);
+ if (fMargin != margin) {
+ fMargin = margin;
+ getParent().layout();
+ redraw();
+ axisTreeCoordinates.y -= margin;
+ height += margin;
+ }
+ return new Rectangle(treeClientArea.x, axisTreeCoordinates.y, treeClientArea.width, height);
+ }
+ }
+
+ @Override
+ protected TimeGraphMarkerAxis createTimeGraphMarkerAxis(Composite parent, @NonNull TimeGraphColorScheme colorScheme, @NonNull ITimeDataProvider timeProvider) {
+ TimeGraphMarkerAxisExtension timeGraphMarkerAxis = new TimeGraphMarkerAxisExtension(parent, colorScheme, timeProvider);
+ Tree tree = fTreeViewer.getTree();
+ tree.addPaintListener(e -> {
+ /*
+ * Draw the marker axis over the tree. Only the name area will
+ * be drawn, since the time area has zero width.
+ */
+ Rectangle bounds = timeGraphMarkerAxis.getAxisBounds();
+ e.gc.setBackground(timeGraphMarkerAxis.getBackground());
+ timeGraphMarkerAxis.drawMarkerAxis(bounds, bounds.width, e.gc);
+ });
+ tree.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ Rectangle bounds = timeGraphMarkerAxis.getAxisBounds();
+ if (bounds.contains(e.x, e.y)) {
+ timeGraphMarkerAxis.mouseDown(e, bounds, bounds.width);
+ }
+ }
+ });
+ tree.getHorizontalBar().addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ tree.redraw();
+ }
+ });
+ return timeGraphMarkerAxis;
+ }
+ }
+
+ /**
+ * The TreeContentProviderWrapper is used to insert filler items after the
+ * elements of the tree's real content provider.