Search in sources :

Example 6 with TimeRange

use of com.efficios.jabberwocky.common.TimeRange in project lttng-scope by lttng.

the class TimeGraphWidget method paintCurrentLocation.

/**
 * Bypass the redraw thread and do a manual redraw of the current location.
 */
@VisibleForTesting
void paintCurrentLocation() {
    TimeRange currentHorizontalPos = getViewContext().getVisibleTimeRange();
    VerticalPosition currentVerticalPos = getCurrentVerticalPosition();
    paintArea(currentHorizontalPos, currentVerticalPos, true, true, 0);
}
Also used : TimeRange(com.efficios.jabberwocky.common.TimeRange) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 7 with TimeRange

use of com.efficios.jabberwocky.common.TimeRange in project lttng-scope by lttng.

the class NavUtils method selectNewTimestamp.

/**
 * Move the selection to the target timestamp. Also update the visible range
 * to be centered on that timestamp, but only if it is outside of the
 * current visible range.
 *
 * This should only be called when reaching the new timestamp is caused by a
 * user action (ie, not simply because another view sent a signal).
 *
 * @param viewer
 *            The viewer on which to work
 * @param timestamp
 *            The timestamp to select, and potentially move to
 */
public static void selectNewTimestamp(TimeGraphWidget viewer, long timestamp) {
    /* Update the selection to the new timestamp. */
    viewer.getControl().updateTimeRangeSelection(TimeRange.of(timestamp, timestamp));
    TimeRange fullTimeGraphRange = viewer.getControl().getViewContext().getCurrentProjectFullRange();
    TimeRange windowRange = ViewGroupContextManager.getCurrent().getVisibleTimeRange();
    long windowStart = windowRange.getStartTime();
    long windowEnd = windowRange.getEndTime();
    if (windowStart <= timestamp && timestamp <= windowEnd) {
        /* Timestamp is still in the visible range, don't touch anything. */
        return;
    }
    /* Update the visible range to the requested timestamp. */
    /* The "span" of the window (aka zoom level) will remain constant. */
    long windowSpan = windowEnd - windowStart;
    if (windowSpan > fullTimeGraphRange.getDuration()) {
        /* Should never happen, but just to be mathematically safe. */
        windowSpan = fullTimeGraphRange.getDuration();
    }
    long newStart = timestamp - (windowSpan / 2);
    long newEnd = newStart + windowSpan;
    /* Clamp the range to the borders of the pane/trace. */
    if (newStart < fullTimeGraphRange.getStartTime()) {
        newStart = fullTimeGraphRange.getStartTime();
        newEnd = newStart + windowSpan;
    } else if (newEnd > fullTimeGraphRange.getEndTime()) {
        newEnd = fullTimeGraphRange.getEndTime();
        newStart = newEnd - windowSpan;
    }
    viewer.getControl().updateVisibleTimeRange(TimeRange.of(newStart, newEnd), true);
}
Also used : TimeRange(com.efficios.jabberwocky.common.TimeRange)

Example 8 with TimeRange

use of com.efficios.jabberwocky.common.TimeRange in project lttng-scope by lttng.

the class TimeGraphWidget method seekVisibleRange.

@Override
public void seekVisibleRange(@Nullable TimeRange newVisibleRange) {
    requireNonNull(newVisibleRange);
    final TimeRange fullTimeGraphRange = getViewContext().getCurrentProjectFullRange();
    /* Update the zoom level */
    long windowTimeRange = newVisibleRange.getDuration();
    double timeGraphVisibleWidth = fTimeGraphScrollPane.getViewportBounds().getWidth();
    if (timeGraphVisibleWidth < 100) {
        /*
             * The view's width is reported as 0 if the widget is not yet part of the
             * scenegraph. Instead target a larger width so that we obtain a value of
             * nanos-per-pixel that makes sense.
             */
        timeGraphVisibleWidth = 2000;
    }
    fNanosPerPixel.set(windowTimeRange / timeGraphVisibleWidth);
    double oldTotalWidth = fTimeGraphPane.getLayoutBounds().getWidth();
    double newTotalWidth = timestampToPaneXPos(fullTimeGraphRange.getEndTime()) - timestampToPaneXPos(fullTimeGraphRange.getStartTime());
    if (newTotalWidth < 1.0) {
        // FIXME
        return;
    }
    double newValue;
    if (newVisibleRange.getStartTime() == fullTimeGraphRange.getStartTime()) {
        newValue = fTimeGraphScrollPane.getHmin();
    } else if (newVisibleRange.getEndTime() == fullTimeGraphRange.getEndTime()) {
        newValue = fTimeGraphScrollPane.getHmax();
    } else {
        /*
             * The "hvalue" is in reference to the beginning of the pane, not
             * the middle point as one could think.
             *
             * Also note that the "scrollable distance" is not simply
             * "timeGraphTotalWidth", it's
             * "timeGraphTotalWidth - timeGraphVisibleWidth". The view does not
             * allow scrolling the start and end edges up to the middle point
             * for example.
             *
             * See http://stackoverflow.com/a/23518314/4227853 for a great
             * explanation.
             */
        double startPos = timestampToPaneXPos(newVisibleRange.getStartTime());
        newValue = startPos / (newTotalWidth - timeGraphVisibleWidth);
    }
    fHScrollListenerStatus.disable();
    try {
        /*
             * If the zoom level changed, resize the pane and relocate its
             * current contents. That way the "intermediate" display before the
             * next repaint will continue showing correct data.
             */
        if (Math.abs(newTotalWidth - oldTotalWidth) > 0.5) {
            /* Resize/reposition the state rectangles */
            double factor = (newTotalWidth / oldTotalWidth);
            fStateLayer.getRenderedStateRectangles().forEach(rect -> {
                rect.setLayoutX(rect.getLayoutX() * factor);
                rect.setWidth(rect.getWidth() * factor);
            });
            /* Reposition the text labels (don't stretch them!) */
            fStateLayer.getRenderedStateLabels().forEach(text -> {
                text.setX(text.getX() * factor);
            });
            /* Reposition the arrows */
            fArrowLayer.getRenderedArrows().forEach(arrow -> {
                arrow.setStartX(arrow.getStartX() * factor);
                arrow.setEndX(arrow.getEndX() * factor);
            });
            /* Reposition the drawn events */
            fDrawnEventLayer.getRenderedEvents().forEach(event -> {
                /*
                     * Drawn events use the "translate" properties to define
                     * their position.
                     */
                event.setTranslateX(event.getTranslateX() * factor);
            });
            /*
                 * Resize the pane itself. Remember min/max are bound to the
                 * "pref" width, so this will change the actual size right away.
                 */
            fTimeGraphPane.setPrefWidth(newTotalWidth);
            /*
                 * Since we changed the size of a child of the scrollpane, it's
                 * important to call layout() on it before setHvalue(). If we
                 * don't, the setHvalue() will apply to the old layout, and the
                 * upcoming pulse will simply revert our changes.
                 */
            fTimeGraphScrollPane.layout();
        }
        fTimeGraphScrollPane.setHvalue(newValue);
    } finally {
        fHScrollListenerStatus.enable();
    }
    /*
         * Redraw the current selection, as it may have moved if we changed the
         * size of the pane.
         */
    redrawSelection();
}
Also used : TimeRange(com.efficios.jabberwocky.common.TimeRange)

Example 9 with TimeRange

use of com.efficios.jabberwocky.common.TimeRange in project lttng-scope by lttng.

the class TimeGraphWidget method paintArea.

/**
 * Paint the specified view area.
 *
 * @param windowRange
 *            The horizontal position where the visible window currently is
 * @param verticalPos
 *            The vertical position where the visible window currently is
 * @param movedHorizontally
 *            If we have moved horizontally since the last redraw. May be
 *            used to skip some operations. If you are not sure say "true".
 * @param movedVertically
 *            If we have moved vertically since the last redraw. May be used
 *            to skip some operations. If you are not sure say "true".
 * @param taskSeqNb
 *            The sequence number of this task, used for logging only
 */
void paintArea(TimeRange windowRange, VerticalPosition verticalPos, boolean movedHorizontally, boolean movedVertically, long taskSeqNb) {
    final TimeRange fullTimeGraphRange = getViewContext().getCurrentProjectFullRange();
    /*
         * Request the needed renders and prepare the corresponding UI objects.
         * We may ask for some padding on each side, clamped by the trace's
         * start and end.
         */
    final long timeRangePadding = Math.round(windowRange.getDuration() * getDebugOptions().renderRangePadding.get());
    final long renderingStartTime = Math.max(fullTimeGraphRange.getStartTime(), windowRange.getStartTime() - timeRangePadding);
    final long renderingEndTime = Math.min(fullTimeGraphRange.getEndTime(), windowRange.getEndTime() + timeRangePadding);
    final TimeRange renderingRange = TimeRange.of(renderingStartTime, renderingEndTime);
    /*
         * Start a new repaint, display the "loading" overlay. The next
         * paint task to finish will put it back to non-visible.
         */
    if (getDebugOptions().isLoadingOverlayEnabled.get()) {
        fTimeGraphLoadingOverlay.fadeIn();
    }
    JabberwockyTask<Void> task = new JabberwockyTask<>("Updating Timegraph " + getName(), it -> {
        // $NON-NLS-1$
        LOGGER.finer(() -> "Starting paint task #" + taskSeqNb);
        ITimeGraphModelProvider modelProvider = getControl().getRenderProvider();
        TimeGraphTreeRender treeRender = modelProvider.getTreeRender();
        if (it.isCancelled()) {
            return null;
        }
        /* Prepare the tree part, if needed */
        if (!treeRender.equals(fLatestTreeRender)) {
            fLatestTreeRender = treeRender;
            fTreeArea.updateTreeContents(treeRender);
        }
        if (it.isCancelled()) {
            return null;
        }
        /* Paint the background. It's very quick so we can do it every time. */
        fBackgroundLayer.drawContents(treeRender, renderingRange, verticalPos, it);
        /*
             * The state rectangles should be redrawn as soon as we move,
             * either horizontally or vertically.
             */
        fStateLayer.setWindowRange(windowRange);
        fStateLayer.drawContents(treeRender, renderingRange, verticalPos, it);
        if (it.isCancelled()) {
            return null;
        }
        /*
             * Arrows and drawn events are drawn for the full vertical
             * range. Only refetch/repaint them if we moved horizontally.
             */
        if (movedHorizontally) {
            fArrowLayer.drawContents(treeRender, renderingRange, verticalPos, it);
            fDrawnEventLayer.drawContents(treeRender, renderingRange, verticalPos, it);
        }
        if (it.isCancelled()) {
            return null;
        }
        /* Painting is finished, turn off the loading overlay */
        Platform.runLater(() -> {
            // $NON-NLS-1$
            LOGGER.finest(() -> "fading out overlay");
            fTimeGraphLoadingOverlay.fadeOut();
            if (fRepaintLatch != null) {
                fRepaintLatch.countDown();
            }
        });
        return null;
    });
    // $NON-NLS-1$
    LOGGER.finer(() -> "Queueing task #" + taskSeqNb);
    /*
         * Attach a listener to the task to receive exceptions thrown within the
         * task.
         */
    task.exceptionProperty().addListener((obs, oldVal, newVal) -> {
        if (newVal != null) {
            newVal.printStackTrace();
        }
    });
    fTaskExecutor.schedule(task);
}
Also used : TimeRange(com.efficios.jabberwocky.common.TimeRange) TimeGraphTreeRender(com.efficios.jabberwocky.views.timegraph.model.render.tree.TimeGraphTreeRender) ITimeGraphModelProvider(com.efficios.jabberwocky.views.timegraph.model.provider.ITimeGraphModelProvider) JabberwockyTask(com.efficios.jabberwocky.task.JabberwockyTask)

Example 10 with TimeRange

use of com.efficios.jabberwocky.common.TimeRange in project lttng-scope by lttng.

the class TimeGraphWidgetSeekTest method testSeekVisibleRange.

private void testSeekVisibleRange(long startTime, long endTime) {
    TimeRange range = TimeRange.of(startTime, endTime);
    seekVisibleRange(range);
    verifyVisibleRange(range);
}
Also used : TimeRange(com.efficios.jabberwocky.common.TimeRange)

Aggregations

TimeRange (com.efficios.jabberwocky.common.TimeRange)16 TimeGraphTreeRender (com.efficios.jabberwocky.views.timegraph.model.render.tree.TimeGraphTreeRender)5 FutureTask (java.util.concurrent.FutureTask)4 Group (javafx.scene.Group)4 Nullable (org.jetbrains.annotations.Nullable)4 TimeGraphModelStateProvider (com.efficios.jabberwocky.views.timegraph.model.provider.states.TimeGraphModelStateProvider)3 TimeGraphStateRender (com.efficios.jabberwocky.views.timegraph.model.render.states.TimeGraphStateRender)3 TimeGraphTreeElement (com.efficios.jabberwocky.views.timegraph.model.render.tree.TimeGraphTreeElement)3 Collections (java.util.Collections)3 List (java.util.List)3 Collectors (java.util.stream.Collectors)3 Platform (javafx.application.Platform)3 JfxUtils (org.lttng.scope.common.jfx.JfxUtils)3 TimeGraphWidget (org.lttng.scope.views.timeline.widgets.timegraph.TimeGraphWidget)3 VerticalPosition (org.lttng.scope.views.timeline.widgets.timegraph.VerticalPosition)3 Collection (java.util.Collection)2 Objects (java.util.Objects)2 Objects.requireNonNull (java.util.Objects.requireNonNull)2 Function (java.util.function.Function)2 Logger (java.util.logging.Logger)2