Skip to content

Handle auto-scrolling and highlighting list monitor index #5961

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/components/monitor-list/monitor-list.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const MonitorList = props => (
<Monitor
draggable={props.draggable}
height={monitorData.height}
highlightItem={monitorData.highlightItem}
id={monitorData.id}
isDiscrete={monitorData.isDiscrete}
key={monitorData.id}
Expand Down
21 changes: 17 additions & 4 deletions src/components/monitor/list-monitor-scroller.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import classNames from 'classnames';
import bindAll from 'lodash.bindall';
import {FormattedMessage} from 'react-intl';

import {Set} from 'immutable';
import styles from './monitor.css';
import {List} from 'react-virtualized';

Expand Down Expand Up @@ -31,13 +31,21 @@ class ListMonitorScroller extends React.Component {
);
}
rowRenderer ({index, key, style}) {
const isHighlighted = this.props.highlightItems.has(index);
return (
<div
className={styles.listRow}
key={key}
style={style}
>
<div className={styles.listIndex}>{index + 1 /* one indexed */}</div>
<div
className={classNames(
styles.listIndex,
{
[styles.highlightIndex]: isHighlighted
}
)}
>{index + 1 /* one indexed */}</div>
<div
className={styles.listValue}
dataIndex={index}
Expand Down Expand Up @@ -74,14 +82,17 @@ class ListMonitorScroller extends React.Component {
);
}
render () {
const {height, values, width, activeIndex, activeValue} = this.props;
const {height, values, width, activeIndex, activeValue, highlightItem} = this.props;
// Keep the active index in view if defined, else must be undefined for List component
const scrollToIndex = activeIndex === null ? undefined : activeIndex; /* eslint-disable-line no-undefined */
const highlightIndex = highlightItem === null ? undefined : highlightItem; // eslint-disable-line no-undefined
const scrollToIndex = activeIndex === null ? highlightIndex : activeIndex; // eslint-disable-line no-undefined
return (
<List
activeIndex={activeIndex}
activeValue={activeValue}
height={(height) - 44 /* Header/footer size, approx */}
highlightItems={this.props.highlightItems.toString()
/* note that this is not an actual prop - it's just there to re-render whenever the list updates */}
noRowsRenderer={this.noRowsRenderer}
rowCount={values.length}
rowHeight={24 /* Row size is same for all rows */}
Expand All @@ -100,6 +111,8 @@ ListMonitorScroller.propTypes = {
categoryColor: PropTypes.string,
draggable: PropTypes.bool,
height: PropTypes.number,
highlightItem: PropTypes.number,
highlightItems: PropTypes.instanceOf(Set),
onActivate: PropTypes.func,
onDeactivate: PropTypes.func,
onFocus: PropTypes.func,
Expand Down
6 changes: 5 additions & 1 deletion src/components/monitor/list-monitor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import {FormattedMessage} from 'react-intl';
import {Set} from 'immutable';
import styles from './monitor.css';
import ListMonitorScroller from './list-monitor-scroller.jsx';

Expand Down Expand Up @@ -57,6 +58,8 @@ ListMonitor.propTypes = {
categoryColor: PropTypes.string.isRequired,
draggable: PropTypes.bool.isRequired,
height: PropTypes.number,
highlightItem: PropTypes.number,
highlightItems: PropTypes.instanceOf(Set),
label: PropTypes.string.isRequired,
onActivate: PropTypes.func,
onAdd: PropTypes.func,
Expand All @@ -74,7 +77,8 @@ ListMonitor.propTypes = {

ListMonitor.defaultProps = {
width: 110,
height: 200
height: 200,
highlightItem: null
};

export default ListMonitor;
4 changes: 4 additions & 0 deletions src/components/monitor/monitor.css
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,7 @@
.footer-length {
text-align: center;
}

.highlight-index {
color: $control-primary;
}
38 changes: 34 additions & 4 deletions src/containers/list-monitor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {connect} from 'react-redux';
import {getEventXY} from '../lib/touch-utils';
import {getVariableValue, setVariableValue} from '../lib/variable-utils';
import ListMonitorComponent from '../components/monitor/list-monitor.jsx';
import {Map} from 'immutable';
import {Map as ImmutableMap, Set} from 'immutable'; // to avoid conflict with built-in Map

class ListMonitor extends React.Component {
constructor (props) {
Expand All @@ -19,15 +19,43 @@ class ListMonitor extends React.Component {
'handleKeyPress',
'handleFocus',
'handleAdd',
'handleResizeMouseDown'
'handleResizeMouseDown',
'unhighlight'
]);

this.state = {
activeIndex: null,
activeValue: null,
width: props.width || 100,
height: props.height || 200
height: props.height || 200,
highlightItems: Set()
};

this.highlightMap = new Map();
}

componentWillReceiveProps (nextProps) {
const newHighlightItem = nextProps.highlightItem;
if (newHighlightItem === this.props.highlightItem) return;
if (newHighlightItem === null) return;
if (this.highlightMap.has(newHighlightItem)) {
clearTimeout(this.highlightMap.get(newHighlightItem));
}
this.highlightMap.set(newHighlightItem, setTimeout(() => this.unhighlight(newHighlightItem), 500));
this.setState({
highlightItems: Set(Array.from(this.highlightMap.keys()))
});
}

componentWillUnmount () {
this.highlightMap.forEach(val => clearTimeout(val));
}

unhighlight (item) {
this.highlightMap.delete(item);
this.setState({
highlightItems: Set(Array.from(this.highlightMap.keys()))
});
}

handleActivate (index) {
Expand Down Expand Up @@ -141,7 +169,7 @@ class ListMonitor extends React.Component {
onMouseMove(ev); // Make sure width/height are up-to-date
window.removeEventListener('mousemove', onMouseMove);
window.removeEventListener('mouseup', onMouseUp);
this.props.vm.runtime.requestUpdateMonitor(Map({
this.props.vm.runtime.requestUpdateMonitor(ImmutableMap({
id: this.props.id,
height: this.state.height,
width: this.state.width
Expand All @@ -168,6 +196,7 @@ class ListMonitor extends React.Component {
activeIndex={this.state.activeIndex}
activeValue={this.state.activeValue}
height={this.state.height}
highlightItems={this.state.highlightItems}
width={this.state.width}
onActivate={this.handleActivate}
onAdd={this.handleAdd}
Expand All @@ -184,6 +213,7 @@ class ListMonitor extends React.Component {

ListMonitor.propTypes = {
height: PropTypes.number,
highlightItem: PropTypes.number,
id: PropTypes.string,
targetId: PropTypes.string,
value: PropTypes.oneOfType([
Expand Down
2 changes: 2 additions & 0 deletions src/containers/monitor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ class Monitor extends React.Component {
{...monitorProps}
draggable={this.props.draggable}
height={this.props.height}
highlightItem={this.props.highlightItem}
isDiscrete={this.props.isDiscrete}
max={this.props.max}
min={this.props.min}
Expand All @@ -225,6 +226,7 @@ Monitor.propTypes = {
addMonitorRect: PropTypes.func.isRequired,
draggable: PropTypes.bool,
height: PropTypes.number,
highlightItem: PropTypes.number,
id: PropTypes.string.isRequired,
intl: intlShape,
isDiscrete: PropTypes.bool,
Expand Down