/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at . */ // @flow import { Component } from "react"; import { toEditorLine } from "../../utils/editor"; import { getDocument, hasDocument } from "../../utils/editor/source-documents"; import { isLoaded } from "../../utils/source"; import { connect } from "react-redux"; import { getVisibleSelectedFrame, getSelectedLocation, getSelectedSource, getPauseCommand } from "../../selectors"; import type { Frame, Location, SourceRecord } from "../../types"; import type { Command } from "../../reducers/types"; type Props = { pauseCommand: Command, selectedFrame: Frame, selectedLocation: Location, selectedSource: SourceRecord }; function isDebugLine(selectedFrame: Frame, selectedLocation: Location) { if (!selectedFrame) { return; } return ( selectedFrame.location.sourceId == selectedLocation.sourceId && selectedFrame.location.line == selectedLocation.line ); } function isDocumentReady(selectedSource, selectedLocation) { return ( selectedLocation && isLoaded(selectedSource) && hasDocument(selectedLocation.sourceId) ); } export class HighlightLine extends Component { isStepping: boolean = false; previousEditorLine: ?number = null; shouldComponentUpdate(nextProps: Props) { const { selectedLocation, selectedSource } = nextProps; return this.shouldSetHighlightLine(selectedLocation, selectedSource); } shouldSetHighlightLine( selectedLocation: Location, selectedSource: SourceRecord ) { const { sourceId, line } = selectedLocation; const editorLine = toEditorLine(sourceId, line); if (!isDocumentReady(selectedSource, selectedLocation)) { return false; } if (this.isStepping && editorLine === this.previousEditorLine) { return false; } return true; } componentDidUpdate(prevProps: Props) { const { pauseCommand, selectedLocation, selectedFrame, selectedSource } = this.props; if (pauseCommand) { this.isStepping = true; } this.clearHighlightLine( prevProps.selectedLocation, prevProps.selectedSource ); this.setHighlightLine(selectedLocation, selectedFrame, selectedSource); } setHighlightLine( selectedLocation: Location, selectedFrame: Frame, selectedSource: SourceRecord ) { const { sourceId, line } = selectedLocation; if (!this.shouldSetHighlightLine(selectedLocation, selectedSource)) { return; } this.isStepping = false; const editorLine = toEditorLine(sourceId, line); this.previousEditorLine = editorLine; if (!line || isDebugLine(selectedFrame, selectedLocation)) { return; } const doc = getDocument(sourceId); doc.addLineClass(editorLine, "line", "highlight-line"); } clearHighlightLine(selectedLocation: Location, selectedSource: SourceRecord) { if (!isDocumentReady(selectedSource, selectedLocation)) { return; } const { line, sourceId } = selectedLocation; const editorLine = toEditorLine(sourceId, line); const doc = getDocument(sourceId); doc.removeLineClass(editorLine, "line", "highlight-line"); } render() { return null; } } export default connect(state => ({ pauseCommand: getPauseCommand(state), selectedFrame: getVisibleSelectedFrame(state), selectedLocation: getSelectedLocation(state), selectedSource: getSelectedSource(state) }))(HighlightLine);