/* 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 { PureComponent } from "react";
import classnames from "classnames";
import { showMenu } from "devtools-contextmenu";
import { getDocument } from "../../utils/editor";
import { breakpointItems, createBreakpointItems } from "./menus/breakpoints";
// eslint-disable-next-line max-len
import type { ColumnBreakpoint as ColumnBreakpointType } from "../../selectors/visibleColumnBreakpoints";
import type { BreakpointItemActions } from "./menus/breakpoints";
import type { Source, Context } from "../../types";
type Bookmark = {
clear: Function
};
type Props = {
cx: Context,
editor: Object,
source: Source,
columnBreakpoint: ColumnBreakpointType,
breakpointActions: BreakpointItemActions
};
const breakpointButton = document.createElement("button");
breakpointButton.innerHTML =
'';
function makeBookmark({ breakpoint }, { onClick, onContextMenu }) {
const bp = breakpointButton.cloneNode(true);
const isActive = breakpoint && !breakpoint.disabled;
const isDisabled = breakpoint && breakpoint.disabled;
const condition = breakpoint && breakpoint.options.condition;
const logValue = breakpoint && breakpoint.options.logValue;
bp.className = classnames("column-breakpoint", {
"has-condition": condition,
"has-log": logValue,
active: isActive,
disabled: isDisabled
});
bp.setAttribute("title", logValue || condition || "");
bp.onclick = onClick;
// NOTE: flow does not know about oncontextmenu
(bp: any).oncontextmenu = onContextMenu;
return bp;
}
export default class ColumnBreakpoint extends PureComponent {
addColumnBreakpoint: Function;
bookmark: ?Bookmark;
addColumnBreakpoint = (nextProps: ?Props) => {
const { columnBreakpoint, source } = nextProps || this.props;
const sourceId = source.id;
const doc = getDocument(sourceId);
if (!doc) {
return;
}
const { line, column } = columnBreakpoint.location;
const widget = makeBookmark(columnBreakpoint, {
onClick: this.onClick,
onContextMenu: this.onContextMenu
});
this.bookmark = doc.setBookmark({ line: line - 1, ch: column }, { widget });
};
clearColumnBreakpoint = () => {
if (this.bookmark) {
this.bookmark.clear();
this.bookmark = null;
}
};
onClick = (event: MouseEvent) => {
event.stopPropagation();
event.preventDefault();
const { cx, columnBreakpoint, breakpointActions } = this.props;
if (columnBreakpoint.breakpoint) {
breakpointActions.removeBreakpoint(cx, columnBreakpoint.breakpoint);
} else {
breakpointActions.addBreakpoint(cx, columnBreakpoint.location);
}
};
onContextMenu = (event: MouseEvent) => {
event.stopPropagation();
event.preventDefault();
const {
cx,
columnBreakpoint: { breakpoint, location },
breakpointActions
} = this.props;
const items = breakpoint
? breakpointItems(cx, breakpoint, breakpointActions)
: createBreakpointItems(cx, location, breakpointActions);
showMenu(event, items);
};
componentDidMount() {
this.addColumnBreakpoint();
}
componentWillUnmount() {
this.clearColumnBreakpoint();
}
componentDidUpdate() {
this.clearColumnBreakpoint();
this.addColumnBreakpoint();
}
render() {
return null;
}
}