Skip to content

Commit

Permalink
implement next/prev and zoom-in/zoom-out buttons on timeline toolbar
Browse files Browse the repository at this point in the history
This makes the "Filters" button prettier too.

Note that a forked version of binary-search-bounds was adopted that fixes
mikolalysenko/binary-search-bounds#5 wherein
new Function() was being used in an eval style that is to be avoided.
  • Loading branch information
asutherland committed May 28, 2018
1 parent 83705ec commit cfd95ce
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 2 deletions.
4 changes: 4 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"dependencies": {
"binary-search-bounds": "github:bvaughn/binary-search-bounds#971e0ecbabcb1e9e657a68bf7cd937598117b688",
"d3-array": "^1.2.1",
"d3-axis": "^1.0.8",
"d3-scale": "^2.0.0",
Expand Down
59 changes: 57 additions & 2 deletions src/grok-ui/components/sheets/trice_timeline.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

import { Accordion, Button, Icon } from 'semantic-ui-react';
import { Menu } from 'semantic-ui-react';

import TriceTimelineVis from '../trice_timeline/timeline_vis.jsx';

Expand Down Expand Up @@ -42,6 +42,10 @@ export default class TriceTimelineSheet extends React.PureComponent {

this.onSeekRequest = this.onSeekRequest.bind(this);
this.onRangeChanged = this.onRangeChanged.bind(this);
this.onZoomIn = this.onZoomIn.bind(this);
this.onZoomOut = this.onZoomOut.bind(this);
this.onMovePrev = this.onMovePrev.bind(this);
this.onMoveNext = this.onMoveNext.bind(this);
}

componentWillMount() {
Expand Down Expand Up @@ -145,10 +149,61 @@ export default class TriceTimelineSheet extends React.PureComponent {
thing.sendSlotMessage('triceLog:filters:seeked', { startBin, endBin });
}

/** Return the underlying vis.js timeline widget to invoke its methods */
get visJsWidget() {
const visJsx = this.visRef.current;
return visJsx.visJsWidget;
}

onZoomIn() {
this.visJsWidget.zoomIn(0.5);
}

onZoomOut() {
this.visJsWidget.zoomOut(0.5);
}

/**
* Move the window so that the first event preceding the visible window is
* brought to the center of the timline.
*/
onMovePrev() {
const triceLog = this.props.triceLog;
const startTime = this.visJsWidget.getWindow().start.valueOf();
const event = triceLog.findfirstEventBeforeItemTime(startTime);
if (event) {
this.visJsWidget.moveTo(event.start);
}
}

onMoveNext() {
const triceLog = this.props.triceLog;
const endTime = this.visJsWidget.getWindow().end.valueOf();
const event = triceLog.findfirstEventAfterItemTime(endTime);
if (event) {
this.visJsWidget.moveTo(event.start);
}
}

render() {
return (
<div>
<Button onClick={ this.onFiltersClicked }>Filters</Button>
<Menu size='small'>
<Menu.Menu>
<Menu.Item icon='zoom in' onClick={ this.onZoomIn } />
<Menu.Item icon='zoom out' onClick={ this.onZoomOut } />
</Menu.Menu>
<Menu.Menu>
<Menu.Item icon='backward' onClick={ this.onMovePrev } />
<Menu.Item icon='forward' onClick={ this.onMoveNext } />
</Menu.Menu>
<Menu.Menu position='right'>
<Menu.Item
name='Filters'
onClick={ this.onFiltersClicked } />
</Menu.Menu>
</Menu>

<TriceTimelineVis ref={ this.visRef }
triceLog={ this.props.triceLog }
onEventClicked={ this.onEventClicked }
Expand Down
8 changes: 8 additions & 0 deletions src/grok-ui/components/trice_timeline/timeline_vis.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ export default class TriceTimelineVis extends DirtyingComponent {
actual.moveTo(time);
}

get visJsWidget() {
return this.timelineRef.current && this.timelineRef.current.$el;
}

componentDidMount() {
this.timeline = this.timelineRef.current.$el;
if (this.props.onRangeChanged) {
Expand All @@ -96,6 +100,10 @@ export default class TriceTimelineVis extends DirtyingComponent {
height: '600px',
zoomMin: 10,
zoomMax: 1 * 1000 * 1000,
// require holding down control to use the scroll-wheel to zoom, otherwise
// it's super weird to scroll and then hit the timeline and have it start
// zooming.
zoomKey: 'ctrlKey',
format: {
minorLabels: function(date/*, scale/*, step*/) {
const relTicks = Math.floor(date * triceLog.SCALE / 1000000);
Expand Down
25 changes: 25 additions & 0 deletions src/grokysis/frontend/trice_log.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import EE from 'eventemitter3';
import bounds from 'binary-search-bounds';

export default class TriceLog extends EE {
constructor({ events, config }) {
Expand All @@ -10,11 +11,15 @@ export default class TriceLog extends EE {
* The events as parsed out of the nd-json file, unfiltered, but with some
* normalizations perormed in place that ideally would have happened during
* trace generation. In particular:
* - Sorted by tick (ascending). We need a sorting invariant and this is
* it.
* - Strings are normalized from `0xf00 "string"` to just `string`. This
* is because the pretty printers are getting involved be helpful, but
* it's not actually that helpful.
*/
this.rawEvents = events;
events.sort((a, b) => a.tick - b.tick);

/**
* The (effective) TOML config file that was used to generate the trace and
* may have display hints built-in. By effective, I mean that this might
Expand Down Expand Up @@ -434,4 +439,24 @@ export default class TriceLog extends EE {
const bin = Math.floor(this.NBINS * relTickTime / tickSpan);
return bin;
}

findfirstEventBeforeItemTime(itemTime) {
// we can stay in scaled space for this.
const idx = bounds.lt(this.filteredVisItems, { start: itemTime },
(a, b) => a.start - b.start);
if (idx === -1) {
return null;
}
return this.filteredVisItems[idx];
}

findfirstEventAfterItemTime(itemTime) {
// we can stay in scaled space for this.
const idx = bounds.gt(this.filteredVisItems, { start: itemTime },
(a, b) => a.start - b.start);
if (idx === -1) {
return null;
}
return this.filteredVisItems[idx];
}
}

0 comments on commit cfd95ce

Please sign in to comment.