Skip to content

Commit

Permalink
Add first version of new flex-layout
Browse files Browse the repository at this point in the history
  • Loading branch information
aranega committed Jan 7, 2025
1 parent 8b89533 commit 2344787
Show file tree
Hide file tree
Showing 107 changed files with 11,778 additions and 8,312 deletions.
27 changes: 0 additions & 27 deletions examples/layout-manager-playground/src/layout/defaultLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,34 +21,7 @@ export default {
id: "root",
weight: 100,
children: [
{
type: "row",
enableDeleteWhenEmpty: true,
weight:60,
children:[
{ type: "row",
id: "top",

children: [{ type: "tabset",
id: "topLeft",
enableDeleteWhenEmpty: false,
children: [] ,
weight: 30,
},{ type: "tabset",
id: "topRight",
enableDeleteWhenEmpty: false,
children: [] ,
weight: 70,
}] ,
weight: 30,
},
{ type: "tabset",
id: "bottom",
enableDeleteWhenEmpty: false,
weight: 70,
children: [] }
]
},

]
}
Expand Down
3 changes: 3 additions & 0 deletions examples/multiple-layout-manager-playground/src/index.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
@import '@fortawesome/fontawesome-free/css/all.min.css';


:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
Expand Down
7 changes: 5 additions & 2 deletions geppetto.js/geppetto-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
"@babel/preset-react": "^7.24.7",
"@babel/preset-typescript": "^7.24.7",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@types/react": "^18.3.1",
"@types/react-redux": "^7.1.34",
"@eslint/js": "^9.9.0",
"babel-jest": "^29.7.0",
"babel-plugin-module-resolver": "^5.0.2",
Expand All @@ -47,14 +49,15 @@
"jest": "^29.7.0",
"less": "^3.9.0",
"nodemon": "^3.1.4",
"typescript": "^4.3.2"
"typescript": "^4.3.2",
"@material-ui/core": "^4.11.4"
},
"peerDepedencies": {
"@metacell/geppetto-meta-core": "^3.0.0-alpha.0",
"@metacell/geppetto-meta-ui": "^3.0.0-alpha.0",
"@material-ui/core": "^4.11.4",
"pako": "^1.0.3",
"react": "^17.0.2",
"react": "^18.3.1",
"react-redux": "^7.2.3",
"react-rnd": "^7.3.0",
"redux": "^4.1.0",
Expand Down
106 changes: 64 additions & 42 deletions geppetto.js/geppetto-client/src/common/layout/LayoutManager.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import * as React from 'react';
import * as FlexLayout from '@metacell/geppetto-meta-ui/flex-layout/src/index';
import Actions from '@metacell/geppetto-meta-ui/flex-layout/src/model/Actions';
import DockLocation from '@metacell/geppetto-meta-ui/flex-layout/src/DockLocation';
import Model from '@metacell/geppetto-meta-ui/flex-layout/src/model/Model';
import {type ComponentMap, type IComponentConfig, type Widget, WidgetStatus} from './model';
import {createStyles, withStyles} from '@material-ui/core/styles'
import { Actions } from '@metacell/geppetto-meta-ui/flex-layout/src/model/Actions';
import { DockLocation } from '@metacell/geppetto-meta-ui/flex-layout/src/DockLocation';
import { Model } from '@metacell/geppetto-meta-ui/flex-layout/src/model/Model';
import { BaseNode, type ComponentMap, type IComponentConfig, type Widget, WidgetStatus } from './model';
import { createStyles, withStyles } from '@material-ui/core/styles'
import WidgetFactory from "./WidgetFactory";
import TabsetIconFactory from "./TabsetIconFactory";
import defaultLayoutConfiguration from "./defaultLayout";
import {getWidget, widget2Node} from "./utils";
import { getWidget, widget2Node } from "./utils";
import * as GeppettoActions from '../actions';

import {layoutActions, removeWidgetFromStore, setLayout, updateLayout,} from "./actions";
import { layoutActions, removeWidgetFromStore, setLayout, updateLayout, } from "./actions";

import {MinimizeHelper} from "./helpers/MinimizeHelper";
import {createTabSet, moveWidget} from "./helpers/FlexLayoutHelper";
import { MinimizeHelper } from "./helpers/MinimizeHelper";
import { createTabSet, moveWidget } from "./helpers/FlexLayoutHelper";
import type { IJsonModel } from '@metacell/geppetto-meta-ui/flex-layout/src/model/IJsonModel';


Expand Down Expand Up @@ -47,7 +47,7 @@ export class LayoutManager {
/**
* Used to restore weights from the default layout
*/
defaultWeights: {[id: string]: number} = {};
defaultWeights: { [id: string]: number } = {};
widgetFactory: WidgetFactory;
tabsetIconFactory: TabsetIconFactory;
store;
Expand Down Expand Up @@ -75,20 +75,26 @@ export class LayoutManager {
: new TabsetIconFactory();
this.middleware = this.middleware.bind(this);
this.factory = this.factory.bind(this);
this.minimizeHelper= new MinimizeHelper(isMinimizeEnabled, this.model)
this.minimizeHelper = new MinimizeHelper(isMinimizeEnabled, this.model)
}



setLayout(model: any) {
this.model = FlexLayout.Model.fromJson(
model || defaultLayoutConfiguration
model || defaultLayoutConfiguration
);
const allNodes: FlexLayout.Node[] = Object.values(this.model._idMap);
for(const node of allNodes) {
this.defaultWeights[node.getId()] = node._getAttr("weight");
}
this.fixRowRecursive(this.model._root)
this.model.visitNodes((node) => {
const fn = (node as BaseNode)?.getWeight;
if (!fn) {
return
}
this.defaultWeights[node.getId()] = fn.bind(node)();
})
// for (const node of allNodes) {
// this.defaultWeights[node.getId()] = (node as BaseNode).getWeight();
// console.log("Visit", node)
// }

this.fixRowRecursive(this.model.getRoot())
}

/**
Expand All @@ -103,7 +109,7 @@ export class LayoutManager {
const { model } = this;
let tabset = model.getNodeById(widgetConfiguration.panelName);
if (tabset === undefined) {
createTabSet(this.model, widgetConfiguration.panelName, widgetConfiguration.defaultPosition, widgetConfiguration.defaultWeight);
tabset = createTabSet(this.model, widgetConfiguration.panelName, widgetConfiguration.defaultPosition, widgetConfiguration.defaultWeight);
}
widgetConfiguration.pos = widgetConfiguration.pos ?? tabset.getChildren().length
this.model.doAction(
Expand Down Expand Up @@ -257,7 +263,7 @@ export class LayoutManager {
* @memberof Control
*/
middleware = (store) => (next) => (action) => {
if(!this.store) {
if (!this.store) {
next(setLayout(JSON.stringify(this.model.toJson())));
}

Expand Down Expand Up @@ -335,42 +341,57 @@ export class LayoutManager {
next(action);
}
if (nextSetLayout) {
this.fixRowRecursive(this.model._root)
this.fixRowRecursive(this.model.getRoot())
next(updateLayout(this.model));
}

};

setTabsetWeight(node: FlexLayout.Node, weight: number) {
this.model.doAction(FlexLayout.Actions.updateNodeAttributes(node.getId(), { weight: 0 }))
}

restoreWeight(node: FlexLayout.Node) {
const baseNode = node as BaseNode;
if (baseNode?.getWeight?.() === 0) {
this.setTabsetWeight(baseNode, this.defaultWeights[baseNode.getId()] ?? 50)
}

if(node._getAttr("weight") == 0) {
node._setWeight(this.defaultWeights[node.getId()] ?? 50);
if (baseNode.getParent()) {
this.restoreWeight(baseNode.getParent());
}
}

if(node.getParent()) {
this.restoreWeight(node.getParent());
containsWidget(node: FlexLayout.Node) {
if (node.getChildren().length === 0 || !node.getChildren().every(n => n.getType() === "tab")) {
return false
}
for (const child of node.getChildren()) {
if (this.containsWidget(child)) {
return true;
}
}
return false
}

fixRowRecursive(node: FlexLayout.Node) {
if(node.getType() === "row" || node.getType() === "tabset") {
if(node.getChildren().length === 0) {
node._setWeight(0);
if (node.getType() === "row" || node.getType() === "tabset") {
if (node.getChildren().length === 0) {
this.setTabsetWeight(node, 0)
return true;
} else {


let empty = true;
for(let child of node.getChildren()) {
empty = this.fixRowRecursive(child) && empty;
for (let child of node.getChildren()) {
empty = this.fixRowRecursive(child) && empty;
}

if(!empty) {
if (!empty) {
this.restoreWeight(node);
} else {
node._setWeight(0);
this.setTabsetWeight(node, 0)
}

return empty;
}
}
Expand Down Expand Up @@ -459,12 +480,12 @@ export class LayoutManager {
break;
}
case Actions.MAXIMIZE_TOGGLE:
// reminder, widgets are not maximised but tabsets are
// reminder, widgets are not maximised but tabsets are
break;
case Actions.RENAME_TAB:
break;
case Actions.ADJUST_SPLIT:
break;
// case Actions.ADJUST_SPLIT:
// break;
case Actions.ADD_NODE: {
break;
}
Expand All @@ -478,7 +499,7 @@ export class LayoutManager {
if (defaultAction) {
this.model.doAction(action);
}
this.fixRowRecursive(this.model._root)
this.fixRowRecursive(this.model.getRoot())

const newModel = this.model.toJson();
if (oldModel !== newModel) {
Expand All @@ -500,7 +521,7 @@ export class LayoutManager {
const mergedWidget = { ...previousWidget, ...widget }

const widgetRestored = this.minimizeHelper.restoreWidgetIfNecessary(previousWidget, mergedWidget);
if(!widgetRestored){
if (!widgetRestored) {
moveWidget(model, mergedWidget);
}

Expand All @@ -514,11 +535,12 @@ export class LayoutManager {
if (mergedWidget.status === WidgetStatus.ACTIVE) {
model.doAction(FlexLayout.Actions.selectTab(mergedWidget.id));
}
if((widget.status === WidgetStatus.MAXIMIZED && !node.getParent().isMaximized()) ||
(widget.status === WidgetStatus.ACTIVE && node.getParent().isMaximized())) {
const parent = node.getParent() as BaseNode;
if ((widget.status === WidgetStatus.MAXIMIZED && !parent.isMaximized()) ||
(widget.status === WidgetStatus.ACTIVE && parent.isMaximized())) {
this.model.doAction(FlexLayout.Actions.maximizeToggle(node.getParent().getId()));
}
else if(widget.status === WidgetStatus.MINIMIZED && !this.minimizeHelper.isMinimized(widget)) {
else if (widget.status === WidgetStatus.MINIMIZED && !this.minimizeHelper.isMinimized(widget)) {
this.minimizeHelper.minimizeWidget(node.getId());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default {
"type": "tabset",
"weight": 100,
"id": "root",
"active": "true",
"children": []
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,41 +16,43 @@ import * as FlexLayout from '@metacell/geppetto-meta-ui/flex-layout/src/index';
export function createTabSet(model, tabsetID, position = TabsetPosition.RIGHT, weight = 50) {
const rootNode = model.getNodeById("root");

const tabset = new FlexLayout.TabSetNode(model, { id: tabsetID });
// const tabset = new FlexLayout.TabSetNode(model, { id: tabsetID });

switch (position) {
case TabsetPosition.RIGHT:
rootNode.getChildren().forEach(node => node._setWeight(100 - weight));
rootNode._addChild(tabset);
break;
case TabsetPosition.LEFT:
rootNode.getChildren().forEach(node => node._setWeight(100 - weight));
rootNode._addChild(tabset, 0);
break;
case TabsetPosition.BOTTOM:
case TabsetPosition.TOP: {
// switch (position) {
// case TabsetPosition.RIGHT:
// rootNode.getChildren().forEach(node => node.setWeight(100 - weight));
// rootNode.addChild(tabset);
// break;
// case TabsetPosition.LEFT:
// rootNode.getChildren().forEach(node => node.setWeight(100 - weight));
// rootNode.addChild(tabset, 0);
// break;
// case TabsetPosition.BOTTOM:
// case TabsetPosition.TOP: {

tabset._setWeight(80);
let hrow = new FlexLayout.RowNode(model, {});
hrow._setWeight(100);
// tabset.setWeight(80);
// const hrow = new FlexLayout.RowNode(model, rootNode.windowId, {});
// hrow.setWeight(100);

rootNode.getChildren().forEach(child => {
if (child['getWeight']) {
const newWeight = (child as FlexLayout.TabSetNode).getWeight() / 2;
child._setWeight(newWeight);
hrow._addChild(child);
}
});
if (position === TabsetPosition.BOTTOM) {
hrow._addChild(tabset)
} else {
hrow._addChild(tabset, 0);
}
// rootNode.getChildren().forEach(child => {
// if (child['getWeight']) {
// const newWeight = (child as FlexLayout.TabSetNode).getWeight() / 2;
// child.setWeight(newWeight);
// hrow.addChild(child);
// }
// });
// if (position === TabsetPosition.BOTTOM) {
// hrow.addChild(tabset)
// } else {
// hrow.addChild(tabset, 0);
// }

rootNode._removeAll();
rootNode._addChild(hrow, 0);
}
}
// rootNode._removeAll();
// rootNode.addChild(hrow, 0);
// }
// }
// return tabset
return undefined
}

export function moveWidget(model, widget) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {Store} from "redux";
import {Widget, WidgetStatus} from "../model";
import {updateWidget} from "../actions";
// @ts-ignore
import Model from '@metacell/geppetto-meta-ui/flex-layout/src/model/Model';
import type { Model } from '@metacell/geppetto-meta-ui/flex-layout/src/model/Model';
import {MINIMIZED_PANEL} from '../../layout';
import {createTabSet, moveWidget} from "./FlexLayoutHelper";

Expand Down Expand Up @@ -60,7 +60,7 @@ export class MinimizeHelper {
*/
minimizeWidget(widgetId) {
if(this.store && this.minimizeBorderID) {

let updatedWidget = { ...getWidget(this.store, widgetId) };
updatedWidget.status = WidgetStatus.MINIMIZED;
updatedWidget.defaultPanel = updatedWidget.panelName;
Expand Down
Loading

0 comments on commit 2344787

Please sign in to comment.