Skip to content
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

TabBar drop #222

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
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
Next Next commit
Allow dropping Tabs on TabBar
  • Loading branch information
ErikSom committed Oct 13, 2023
commit 156b144d91d551793bcef4a9bebcae1661b55224
14 changes: 14 additions & 0 deletions es/DockLayout.js
Original file line number Diff line number Diff line change
@@ -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;
2 changes: 2 additions & 0 deletions es/DockPanel.d.ts
Original file line number Diff line number Diff line change
@@ -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;
69 changes: 68 additions & 1 deletion es/DockPanel.js
Original file line number Diff line number Diff line change
@@ -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() {
@@ -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) {
@@ -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 }),
2 changes: 2 additions & 0 deletions es/DockTabBar.d.ts
Original file line number Diff line number Diff line change
@@ -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;
4 changes: 2 additions & 2 deletions es/DockTabBar.js
Original file line number Diff line number Diff line change
@@ -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) => {
@@ -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
@@ -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>;
4 changes: 2 additions & 2 deletions es/DockTabs.js
Original file line number Diff line number Diff line change
@@ -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;
@@ -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;
14 changes: 14 additions & 0 deletions lib/DockLayout.js
Original file line number Diff line number Diff line change
@@ -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;
2 changes: 2 additions & 0 deletions lib/DockPanel.d.ts
Original file line number Diff line number Diff line change
@@ -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;
69 changes: 68 additions & 1 deletion lib/DockPanel.js
Original file line number Diff line number Diff line change
@@ -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() {
@@ -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) {
@@ -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 }),
2 changes: 2 additions & 0 deletions lib/DockTabBar.d.ts
Original file line number Diff line number Diff line change
@@ -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;
4 changes: 2 additions & 2 deletions lib/DockTabBar.js
Original file line number Diff line number Diff line change
@@ -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) => {
@@ -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
@@ -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>;
4 changes: 2 additions & 2 deletions lib/DockTabs.js
Original file line number Diff line number Diff line change
@@ -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;
@@ -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;
18 changes: 18 additions & 0 deletions src/DockLayout.tsx
Original file line number Diff line number Diff line change
@@ -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;
Loading