import * as React from "react"; import { I18nLabel } from "../I18nLabel"; import Actions from "../model/Actions"; import TabNode from "../model/TabNode"; import TabSetNode from "../model/TabSetNode"; import Rect from "../Rect"; import { IIcons, ILayoutCallbacks, ITitleObject } from "./Layout"; import { ICloseType } from "../model/ICloseType"; import { CLASSES } from "../Types"; import { isAuxMouseEvent } from "./TabSet"; /** @hidden @internal */ export interface ITabButtonProps { layout: ILayoutCallbacks; node: TabNode; selected: boolean; height: number; iconFactory?: (node: TabNode) => React.ReactNode | undefined; titleFactory?: (node: TabNode) => React.ReactNode | undefined; icons?: IIcons; path: string; } /** @hidden @internal */ export const TabButton = (props: ITabButtonProps) => { const { layout, node, selected, iconFactory, titleFactory, icons, path } = props; const selfRef = React.useRef(null); const contentRef = React.useRef(null); const contentWidth = React.useRef(0); const onMouseDown = (event: React.MouseEvent | React.TouchEvent) => { if (!isAuxMouseEvent(event) && !layout.getEditingTab()) { const message = layout.i18nName(I18nLabel.Move_Tab, node.getName()); layout.dragStart(event, message, node, node.isEnableDrag(), onClick, onDoubleClick); } }; const onAuxMouseClick = (event: React.MouseEvent) => { if (isAuxMouseEvent(event)) { layout.auxMouseClick(node, event); } }; const onContextMenu = (event: React.MouseEvent) => { layout.showContextMenu(node, event); }; const onClick = () => { layout.doAction(Actions.selectTab(node.getId())); }; const onDoubleClick = (event: Event) => { if (node.isEnableRename()) { layout.setEditingTab(node); layout.getCurrentDocument()!.body.addEventListener("mousedown", onEndEdit); layout.getCurrentDocument()!.body.addEventListener("touchstart", onEndEdit); } // else { // const parentNode = node.getParent() as TabSetNode; // if (parentNode.canMaximize()) { // layout.maximize(parentNode); // } // } }; const onEndEdit = (event: Event) => { if (event.target !== contentRef.current!) { layout.getCurrentDocument()!.body.removeEventListener("mousedown", onEndEdit); layout.getCurrentDocument()!.body.removeEventListener("touchstart", onEndEdit); layout.setEditingTab(undefined); } }; const isClosable = () => { const closeType = node.getCloseType(); if (selected || closeType === ICloseType.Always) { return true; } if (closeType === ICloseType.Visible) { // not selected but x should be visible due to hover if (window.matchMedia && window.matchMedia("(hover: hover) and (pointer: fine)").matches) { return true; } } return false; }; const onClose = (event: React.MouseEvent) => { if (isClosable()) { layout.doAction(Actions.deleteTab(node.getId())); } else { onClick(); } }; const onCloseMouseDown = (event: React.MouseEvent | React.TouchEvent) => { event.stopPropagation(); }; React.useLayoutEffect(() => { updateRect(); if (layout.getEditingTab() === node) { (contentRef.current! as HTMLInputElement).select(); } }); const updateRect = () => { // record position of tab in node const layoutRect = layout.getDomRect(); const r = selfRef.current!.getBoundingClientRect(); node._setTabRect(new Rect(r.left - layoutRect.left, r.top - layoutRect.top, r.width, r.height)); contentWidth.current = contentRef.current!.getBoundingClientRect().width; }; const onTextBoxMouseDown = (event: React.MouseEvent | React.TouchEvent) => { // console.log("onTextBoxMouseDown"); event.stopPropagation(); }; const onTextBoxKeyPress = (event: React.KeyboardEvent) => { // console.log(event, event.keyCode); if (event.keyCode === 27) { // esc layout.setEditingTab(undefined); } else if (event.keyCode === 13) { // enter layout.setEditingTab(undefined); layout.doAction(Actions.renameTab(node.getId(), (event.target as HTMLInputElement).value)); } }; const cm = layout.getClassName; const parentNode = node.getParent() as TabSetNode; let baseClassName = CLASSES.FLEXLAYOUT__TAB_BUTTON; let classNames = cm(baseClassName); classNames += " " + cm(baseClassName + "_" + parentNode.getTabLocation()); if (selected) { classNames += " " + cm(baseClassName + "--selected"); } else { classNames += " " + cm(baseClassName + "--unselected"); } if (node.getClassName() !== undefined) { classNames += " " + node.getClassName(); } let leadingContent = iconFactory ? iconFactory(node) : undefined; let titleContent: React.ReactNode = node.getName(); let name = node.getName(); function isTitleObject(obj: any): obj is ITitleObject { return obj.titleContent !== undefined } if (titleFactory !== undefined) { const titleObj = titleFactory(node); if (titleObj !== undefined) { if (typeof titleObj === "string") { titleContent = titleObj as string; name = titleObj as string; } else if (isTitleObject(titleObj)) { titleContent = titleObj.titleContent; name = titleObj.name; } else { titleContent = titleObj; } } } if (leadingContent === undefined && node.getIcon() !== undefined) { leadingContent = leadingContent; } let buttons: any[] = []; // allow customization of leading contents (icon) and contents const renderState = { leading: leadingContent, content: titleContent, name, buttons }; layout.customizeTab(node, renderState); node._setRenderedName(renderState.name); let content = (
{renderState.content}
); const leading =
{renderState.leading}
; if (layout.getEditingTab() === node) { const contentStyle = { width: contentWidth + "px" }; content = ( ); } if (node.isEnableClose()) { const closeTitle = layout.i18nName(I18nLabel.Close_Tab); buttons.push(
{icons?.close}
); } return (
{leading} {content} {buttons}
); };