Skip to content

Commit

Permalink
Allow dropping Tabs on TabBar
Browse files Browse the repository at this point in the history
  • Loading branch information
ErikSom committed Oct 13, 2023
1 parent 8b6481d commit 156b144
Show file tree
Hide file tree
Showing 18 changed files with 281 additions and 15 deletions.
14 changes: 14 additions & 0 deletions es/DockLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,20 @@ export class DockLayout extends DockPortalManager {
if (element.classList.contains('dock-box')) {
ratio = 0.3;
}
if (direction === 'after-tab') {
const navWidth = 30;
const extraContentWidth = 30;
// search parents until we find .dock-nav
let parent = element.parentElement;
while (parent && !parent.classList.contains('dock-nav')) {
parent = parent.parentElement;
}
if (parent) {
const parentRect = parent.getBoundingClientRect();
// make sure left is lower then parent right
left = Math.min(left, parentRect.right - navWidth - extraContentWidth - width);
}
}
switch (direction) {
case 'float': {
let x = (event.clientX - layoutRect.left) * scaleX;
Expand Down
2 changes: 2 additions & 0 deletions es/DockPanel.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ export declare class DockPanel extends React.PureComponent<Props, State> {
onPanelCornerDragEnd: (e: DragState) => void;
onFloatPointerDown: () => void;
onPanelClicked: (e: React.MouseEvent) => void;
onPanelDragOver: (e: DragState) => void;
onPanelDrop: (e: DragState) => void;
render(): React.ReactNode;
_unmounted: boolean;
componentWillUnmount(): void;
Expand Down
69 changes: 68 additions & 1 deletion es/DockPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { DockDropLayer } from "./DockDropLayer";
import { getFloatPanelSize, nextZIndex } from "./Algorithm";
import { DockDropEdge } from "./DockDropEdge";
import { groupClassNames } from "./Utils";
import * as DragManager from "./dragdrop/DragManager";
import classNames from "classnames";
export class DockPanel extends React.PureComponent {
constructor() {
Expand Down Expand Up @@ -204,6 +205,72 @@ export class DockPanel extends React.PureComponent {
this._ref.querySelector('.dock-bar').focus();
}
};
this.onPanelDragOver = (e) => {
var _a, _b;
let dockId = this.context.getDockId();
let tab = DragManager.DragState.getData('tab', dockId);
let panel = DragManager.DragState.getData('panel', dockId);
let group;
if (tab) {
panel = tab.parent;
group = tab.group;
}
else {
// drag whole panel
if (!panel) {
return;
}
if (panel === null || panel === void 0 ? void 0 : panel.panelLock) {
e.reject();
return;
}
group = panel.group;
}
const tabGroup = this.context.getGroup(group);
const thisPanelData = this.props.panelData;
const lastTab = thisPanelData.tabs[thisPanelData.tabs.length - 1];
const direction = 'after-tab';
const dockTabElements = this._ref.querySelectorAll('.dock-tab');
const dockTabLastElement = dockTabElements[dockTabElements.length - 1];
const dockTabLastRect = dockTabLastElement.querySelector('.dock-tab-hit-area');
if (e.clientX - this._ref.offsetLeft < 30) {
// do not allow drop on the left side of the tab
}
else if (group !== lastTab.group) {
e.reject();
}
else if ((tabGroup === null || tabGroup === void 0 ? void 0 : tabGroup.floatable) === 'singleTab' && ((_b = (_a = lastTab.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.mode) === 'float') {
e.reject();
}
else if (tab && tab !== lastTab) {
this.context.setDropRect(dockTabLastRect, direction, this);
e.accept('');
}
else if (panel && panel !== lastTab.parent) {
this.context.setDropRect(dockTabLastRect, direction, this);
e.accept('');
}
};
this.onPanelDrop = (e) => {
let dockId = this.context.getDockId();
let panel;
let tab = DragManager.DragState.getData('tab', dockId);
if (tab) {
panel = tab.parent;
}
else {
panel = DragManager.DragState.getData('panel', dockId);
}
const direction = 'after-tab';
const thisPanelData = this.props.panelData;
const lastTab = thisPanelData.tabs[thisPanelData.tabs.length - 1];
if (tab && tab !== lastTab) {
this.context.dockMove(tab, lastTab, direction);
}
else if (panel && panel !== lastTab.parent) {
this.context.dockMove(panel, lastTab, direction);
}
};
this._unmounted = false;
}
static set droppingPanel(panel) {
Expand Down Expand Up @@ -290,7 +357,7 @@ export class DockPanel extends React.PureComponent {
}
}
return (React.createElement(DragDropDiv, { getRef: this.getRef, className: cls, style: style, "data-dockid": id, onDragOverT: isFloat ? null : this.onDragOver, onClick: this.onPanelClicked },
React.createElement(DockTabs, { panelData: panelData, onPanelDragStart: onPanelHeaderDragStart, onPanelDragMove: this.onPanelHeaderDragMove, onPanelDragEnd: this.onPanelHeaderDragEnd }),
React.createElement(DockTabs, { panelData: panelData, onPanelDragStart: onPanelHeaderDragStart, onPanelDragMove: this.onPanelHeaderDragMove, onPanelDragEnd: this.onPanelHeaderDragEnd, onPanelDragOver: this.onPanelDragOver, onPanelDrop: this.onPanelDrop }),
isFloat ?
[
React.createElement(DragDropDiv, { key: "drag-size-t", className: "dock-panel-drag-size dock-panel-drag-size-t", onDragStartT: this.onPanelCornerDragT, onDragMoveT: this.onPanelCornerDragMove, onDragEndT: this.onPanelCornerDragEnd }),
Expand Down
2 changes: 2 additions & 0 deletions es/DockTabBar.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ interface DockTabBarProps extends TabNavListProps {
onDragStart?: DragManager.DragHandler;
onDragMove?: DragManager.DragHandler;
onDragEnd?: DragManager.DragHandler;
onDragOver?: DragManager.DragHandler;
onDrop?: DragManager.DropHandler;
TabNavList: React.ComponentType<TabNavListProps>;
}
export declare function DockTabBar(props: DockTabBarProps): JSX.Element;
Expand Down
4 changes: 2 additions & 2 deletions es/DockTabBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ function checkLocalTabMove(key, tabbar) {
return false;
}
export function DockTabBar(props) {
const { onDragStart, onDragMove, onDragEnd, TabNavList, isMaximized } = props, restProps = __rest(props, ["onDragStart", "onDragMove", "onDragEnd", "TabNavList", "isMaximized"]);
const { onDragStart, onDragMove, onDragEnd, onDragOver, onDrop, TabNavList, isMaximized } = props, restProps = __rest(props, ["onDragStart", "onDragMove", "onDragEnd", "onDragOver", "onDrop", "TabNavList", "isMaximized"]);
const layout = React.useContext(DockContextType);
const ref = React.useRef();
const getRef = (div) => {
Expand All @@ -55,6 +55,6 @@ export function DockTabBar(props) {
e.preventDefault();
}
};
return (React.createElement(DragDropDiv, { onDragStartT: onDragStart, onDragMoveT: onDragMove, onDragEndT: onDragEnd, role: "tablist", className: "dock-bar", onKeyDown: onKeyDown, getRef: getRef, tabIndex: -1 },
return (React.createElement(DragDropDiv, { onDragStartT: onDragStart, onDragMoveT: onDragMove, onDragEndT: onDragEnd, onDragOverT: onDragOver, onDropT: onDrop, role: "tablist", className: "dock-bar", onKeyDown: onKeyDown, getRef: getRef, tabIndex: -1 },
React.createElement(TabNavList, Object.assign({}, restProps))));
}
2 changes: 2 additions & 0 deletions es/DockTabs.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ interface Props {
onPanelDragStart: DragManager.DragHandler;
onPanelDragMove: DragManager.DragHandler;
onPanelDragEnd: DragManager.DragHandler;
onPanelDragOver: DragManager.DragHandler;
onPanelDrop: DragManager.DragHandler;
}
export declare class DockTabs extends React.PureComponent<Props> {
static contextType: React.Context<DockContext>;
Expand Down
4 changes: 2 additions & 2 deletions es/DockTabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export class DockTabs extends React.PureComponent {
this.context.dockMove(panelData, null, 'new-window');
};
this.renderTabBar = (props, TabNavList) => {
let { panelData, onPanelDragStart, onPanelDragMove, onPanelDragEnd } = this.props;
let { panelData, onPanelDragStart, onPanelDragMove, onPanelDragEnd, onPanelDragOver, onPanelDrop } = this.props;
let { group: groupName, panelLock } = panelData;
let group = this.context.getGroup(groupName);
let { panelExtra } = group;
Expand All @@ -197,7 +197,7 @@ export class DockTabs extends React.PureComponent {
panelExtraContent = this.addNewWindowMenu(panelExtraContent, !maximizable);
}
}
return (React.createElement(DockTabBar, Object.assign({ onDragStart: onPanelDragStart, onDragMove: onPanelDragMove, onDragEnd: onPanelDragEnd, TabNavList: TabNavList, isMaximized: panelData.parent.mode === 'maximize' }, props, { extra: panelExtraContent })));
return (React.createElement(DockTabBar, Object.assign({ onDragStart: onPanelDragStart, onDragMove: onPanelDragMove, onDragEnd: onPanelDragEnd, onDragOver: onPanelDragOver, onDrop: onPanelDrop, TabNavList: TabNavList, isMaximized: panelData.parent.mode === 'maximize' }, props, { extra: panelExtraContent })));
};
this.onTabChange = (activeId) => {
this.props.panelData.activeId = activeId;
Expand Down
14 changes: 14 additions & 0 deletions lib/DockLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,20 @@ class DockLayout extends DockPortalManager {
if (element.classList.contains('dock-box')) {
ratio = 0.3;
}
if (direction === 'after-tab') {
const navWidth = 30;
const extraContentWidth = 30;
// search parents until we find .dock-nav
let parent = element.parentElement;
while (parent && !parent.classList.contains('dock-nav')) {
parent = parent.parentElement;
}
if (parent) {
const parentRect = parent.getBoundingClientRect();
// make sure left is lower then parent right
left = Math.min(left, parentRect.right - navWidth - extraContentWidth - width);
}
}
switch (direction) {
case 'float': {
let x = (event.clientX - layoutRect.left) * scaleX;
Expand Down
2 changes: 2 additions & 0 deletions lib/DockPanel.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ export declare class DockPanel extends React.PureComponent<Props, State> {
onPanelCornerDragEnd: (e: DragState) => void;
onFloatPointerDown: () => void;
onPanelClicked: (e: React.MouseEvent) => void;
onPanelDragOver: (e: DragState) => void;
onPanelDrop: (e: DragState) => void;
render(): React.ReactNode;
_unmounted: boolean;
componentWillUnmount(): void;
Expand Down
69 changes: 68 additions & 1 deletion lib/DockPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const DockDropLayer_1 = require("./DockDropLayer");
const Algorithm_1 = require("./Algorithm");
const DockDropEdge_1 = require("./DockDropEdge");
const Utils_1 = require("./Utils");
const DragManager = __importStar(require("./dragdrop/DragManager"));
const classnames_1 = __importDefault(require("classnames"));
class DockPanel extends React.PureComponent {
constructor() {
Expand Down Expand Up @@ -229,6 +230,72 @@ class DockPanel extends React.PureComponent {
this._ref.querySelector('.dock-bar').focus();
}
};
this.onPanelDragOver = (e) => {
var _a, _b;
let dockId = this.context.getDockId();
let tab = DragManager.DragState.getData('tab', dockId);
let panel = DragManager.DragState.getData('panel', dockId);
let group;
if (tab) {
panel = tab.parent;
group = tab.group;
}
else {
// drag whole panel
if (!panel) {
return;
}
if (panel === null || panel === void 0 ? void 0 : panel.panelLock) {
e.reject();
return;
}
group = panel.group;
}
const tabGroup = this.context.getGroup(group);
const thisPanelData = this.props.panelData;
const lastTab = thisPanelData.tabs[thisPanelData.tabs.length - 1];
const direction = 'after-tab';
const dockTabElements = this._ref.querySelectorAll('.dock-tab');
const dockTabLastElement = dockTabElements[dockTabElements.length - 1];
const dockTabLastRect = dockTabLastElement.querySelector('.dock-tab-hit-area');
if (e.clientX - this._ref.offsetLeft < 30) {
// do not allow drop on the left side of the tab
}
else if (group !== lastTab.group) {
e.reject();
}
else if ((tabGroup === null || tabGroup === void 0 ? void 0 : tabGroup.floatable) === 'singleTab' && ((_b = (_a = lastTab.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.mode) === 'float') {
e.reject();
}
else if (tab && tab !== lastTab) {
this.context.setDropRect(dockTabLastRect, direction, this);
e.accept('');
}
else if (panel && panel !== lastTab.parent) {
this.context.setDropRect(dockTabLastRect, direction, this);
e.accept('');
}
};
this.onPanelDrop = (e) => {
let dockId = this.context.getDockId();
let panel;
let tab = DragManager.DragState.getData('tab', dockId);
if (tab) {
panel = tab.parent;
}
else {
panel = DragManager.DragState.getData('panel', dockId);
}
const direction = 'after-tab';
const thisPanelData = this.props.panelData;
const lastTab = thisPanelData.tabs[thisPanelData.tabs.length - 1];
if (tab && tab !== lastTab) {
this.context.dockMove(tab, lastTab, direction);
}
else if (panel && panel !== lastTab.parent) {
this.context.dockMove(panel, lastTab, direction);
}
};
this._unmounted = false;
}
static set droppingPanel(panel) {
Expand Down Expand Up @@ -315,7 +382,7 @@ class DockPanel extends React.PureComponent {
}
}
return (React.createElement(DragDropDiv_1.DragDropDiv, { getRef: this.getRef, className: cls, style: style, "data-dockid": id, onDragOverT: isFloat ? null : this.onDragOver, onClick: this.onPanelClicked },
React.createElement(DockTabs_1.DockTabs, { panelData: panelData, onPanelDragStart: onPanelHeaderDragStart, onPanelDragMove: this.onPanelHeaderDragMove, onPanelDragEnd: this.onPanelHeaderDragEnd }),
React.createElement(DockTabs_1.DockTabs, { panelData: panelData, onPanelDragStart: onPanelHeaderDragStart, onPanelDragMove: this.onPanelHeaderDragMove, onPanelDragEnd: this.onPanelHeaderDragEnd, onPanelDragOver: this.onPanelDragOver, onPanelDrop: this.onPanelDrop }),
isFloat ?
[
React.createElement(DragDropDiv_1.DragDropDiv, { key: "drag-size-t", className: "dock-panel-drag-size dock-panel-drag-size-t", onDragStartT: this.onPanelCornerDragT, onDragMoveT: this.onPanelCornerDragMove, onDragEndT: this.onPanelCornerDragEnd }),
Expand Down
2 changes: 2 additions & 0 deletions lib/DockTabBar.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ interface DockTabBarProps extends TabNavListProps {
onDragStart?: DragManager.DragHandler;
onDragMove?: DragManager.DragHandler;
onDragEnd?: DragManager.DragHandler;
onDragOver?: DragManager.DragHandler;
onDrop?: DragManager.DropHandler;
TabNavList: React.ComponentType<TabNavListProps>;
}
export declare function DockTabBar(props: DockTabBarProps): JSX.Element;
Expand Down
4 changes: 2 additions & 2 deletions lib/DockTabBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ function checkLocalTabMove(key, tabbar) {
return false;
}
function DockTabBar(props) {
const { onDragStart, onDragMove, onDragEnd, TabNavList, isMaximized } = props, restProps = __rest(props, ["onDragStart", "onDragMove", "onDragEnd", "TabNavList", "isMaximized"]);
const { onDragStart, onDragMove, onDragEnd, onDragOver, onDrop, TabNavList, isMaximized } = props, restProps = __rest(props, ["onDragStart", "onDragMove", "onDragEnd", "onDragOver", "onDrop", "TabNavList", "isMaximized"]);
const layout = React.useContext(DockData_1.DockContextType);
const ref = React.useRef();
const getRef = (div) => {
Expand All @@ -77,7 +77,7 @@ function DockTabBar(props) {
e.preventDefault();
}
};
return (React.createElement(DragDropDiv_1.DragDropDiv, { onDragStartT: onDragStart, onDragMoveT: onDragMove, onDragEndT: onDragEnd, role: "tablist", className: "dock-bar", onKeyDown: onKeyDown, getRef: getRef, tabIndex: -1 },
return (React.createElement(DragDropDiv_1.DragDropDiv, { onDragStartT: onDragStart, onDragMoveT: onDragMove, onDragEndT: onDragEnd, onDragOverT: onDragOver, onDropT: onDrop, role: "tablist", className: "dock-bar", onKeyDown: onKeyDown, getRef: getRef, tabIndex: -1 },
React.createElement(TabNavList, Object.assign({}, restProps))));
}
exports.DockTabBar = DockTabBar;
2 changes: 2 additions & 0 deletions lib/DockTabs.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ interface Props {
onPanelDragStart: DragManager.DragHandler;
onPanelDragMove: DragManager.DragHandler;
onPanelDragEnd: DragManager.DragHandler;
onPanelDragOver: DragManager.DragHandler;
onPanelDrop: DragManager.DragHandler;
}
export declare class DockTabs extends React.PureComponent<Props> {
static contextType: React.Context<DockContext>;
Expand Down
4 changes: 2 additions & 2 deletions lib/DockTabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ class DockTabs extends React.PureComponent {
this.context.dockMove(panelData, null, 'new-window');
};
this.renderTabBar = (props, TabNavList) => {
let { panelData, onPanelDragStart, onPanelDragMove, onPanelDragEnd } = this.props;
let { panelData, onPanelDragStart, onPanelDragMove, onPanelDragEnd, onPanelDragOver, onPanelDrop } = this.props;
let { group: groupName, panelLock } = panelData;
let group = this.context.getGroup(groupName);
let { panelExtra } = group;
Expand All @@ -223,7 +223,7 @@ class DockTabs extends React.PureComponent {
panelExtraContent = this.addNewWindowMenu(panelExtraContent, !maximizable);
}
}
return (React.createElement(DockTabBar_1.DockTabBar, Object.assign({ onDragStart: onPanelDragStart, onDragMove: onPanelDragMove, onDragEnd: onPanelDragEnd, TabNavList: TabNavList, isMaximized: panelData.parent.mode === 'maximize' }, props, { extra: panelExtraContent })));
return (React.createElement(DockTabBar_1.DockTabBar, Object.assign({ onDragStart: onPanelDragStart, onDragMove: onPanelDragMove, onDragEnd: onPanelDragEnd, onDragOver: onPanelDragOver, onDrop: onPanelDrop, TabNavList: TabNavList, isMaximized: panelData.parent.mode === 'maximize' }, props, { extra: panelExtraContent })));
};
this.onTabChange = (activeId) => {
this.props.panelData.activeId = activeId;
Expand Down
18 changes: 18 additions & 0 deletions src/DockLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,24 @@ export class DockLayout extends DockPortalManager implements DockContext {
if (element.classList.contains('dock-box')) {
ratio = 0.3;
}

if(direction === 'after-tab'){
const navWidth = 30;
const extraContentWidth = 30;

// search parents until we find .dock-nav
let parent = element.parentElement;
while(parent && !parent.classList.contains('dock-nav')){
parent = parent.parentElement;
}

if(parent){
const parentRect = parent.getBoundingClientRect();
// make sure left is lower then parent right
left = Math.min(left, parentRect.right - navWidth - extraContentWidth - width);
}
}

switch (direction) {
case 'float': {
let x = (event.clientX - layoutRect.left) * scaleX;
Expand Down
Loading

0 comments on commit 156b144

Please sign in to comment.