Skip to content

Commit

Permalink
v0.7.11
Browse files Browse the repository at this point in the history
  • Loading branch information
nealus committed Sep 16, 2023
1 parent 83de89c commit 82ce11c
Show file tree
Hide file tree
Showing 13 changed files with 111 additions and 56 deletions.
7 changes: 7 additions & 0 deletions ChangeLog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
0.7.11
Added ITabSetRenderValues.overflowPosition to allow overflow button position to be
specified, if left undefined, position will be after sticky buttons as before.
New model attribute enableRotateBorderIcons, this allows the tab icons in the left and
right borders to rotate with the text or not, default is true.
Added additional class names to edge indicators

0.7.10
Fix for #399 - the overflow button in a tabset is now placed after
any sticky buttons (additional buttons that stick to the last tab of a tabset)
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ Attributes allowed in the 'global' element
| splitterExtra | 0 | additional width in pixels of the splitter hit test area |
| legacyOverflowMenu | false | use the legacy text only overflow menu |
| enableEdgeDock | true | |
| enableRotateBorderIcons | true | boolean indicating if tab icons should rotate with the text in the left and right borders |
| tabEnableClose | true | allow user to close all tabs via close button |
| tabCloseType | 1 | see values in ICloseType |
| tabEnableDrag | true | allow user to drag all tabs to new location |
Expand Down Expand Up @@ -446,7 +447,7 @@ Note: tabsets can be dynamically created as tabs are moved and deleted when all
| name | null | named tabsets will show a header bar above the tabs |
| config | null | a place to hold json config used in your own code |
| selected | 0 | index of selected/visible tab in tabset |
| active | false | whether tabset is currently active; this attribute can only be used in the initial configuration, to change the active tabset you should use the `setActiveTabset` action on the model |
| active | false | whether tabset is currently active; this attribute can only be used in the initial configuration, to change the active tabset you should use the `setActiveTabset` action on the model |
| maximized | false | whether tabset is currently maximized to fill view |
| enableClose | false | allow user to close tabset via a close button |
| id | auto generated | |
Expand Down
3 changes: 3 additions & 0 deletions examples/demo/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,9 @@ class App extends React.Component<any, { layoutFile: string | null, model: Model
className="flexlayout__tab_toolbar_button"
onClick={() => this.onAddFromTabSetButton(node)}
/>);

// put overflow button before + button (default is after)
// renderValues.overflowPosition=0
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion examples/demo/layouts/default.layout
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"tabEnableFloat": true,
"tabSetMinHeight":100,
"tabSetMinWidth":100,
"borderMinSize":100
"borderMinSize":100,
"enableRotateBorderIcons":true
},
"layout": {
"type": "row",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "flexlayout-react",
"version": "0.7.10",
"version": "0.7.11",
"description": "A multi-tab docking layout manager",
"main": "lib/index.js",
"types": "./declarations/index.d.ts",
Expand Down
5 changes: 5 additions & 0 deletions src/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ export enum CLASSES {
FLEXLAYOUT__BORDER_TOOLBAR_BUTTON_FLOAT = "flexlayout__border_toolbar_button-float",

FLEXLAYOUT__DRAG_RECT = "flexlayout__drag_rect",

FLEXLAYOUT__EDGE_RECT = "flexlayout__edge_rect",
FLEXLAYOUT__EDGE_RECT_TOP = "flexlayout__edge_rect_top",
FLEXLAYOUT__EDGE_RECT_LEFT = "flexlayout__edge_rect_left",
FLEXLAYOUT__EDGE_RECT_BOTTOM = "flexlayout__edge_rect_bottom",
FLEXLAYOUT__EDGE_RECT_RIGHT = "flexlayout__edge_rect_right",

FLEXLAYOUT__ERROR_BOUNDARY_CONTAINER = "flexlayout__error_boundary_container",
FLEXLAYOUT__ERROR_BOUNDARY_CONTENT = "flexlayout__error_boundary_content",
Expand Down
5 changes: 5 additions & 0 deletions src/model/IJsonModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export interface IGlobalAttributes {
borderSize?: number; // default: 200
enableEdgeDock?: boolean; // default: true
enableUseVisibility?: boolean; // default: false
enableRotateBorderIcons?: boolean; // default: true
legacyOverflowMenu?: boolean; // default: false
marginInsets?: IInsets; // default: {"top":0,"right":0,"bottom":0,"left":0}
rootOrientationVertical?: boolean; // default: false
Expand Down Expand Up @@ -108,6 +109,10 @@ export interface ITabSetAttributes {
type: "tabset";
weight?: number; // default: 100
width?: number;

// special attributes are read from initial json but must subseqently be set on the model
maximized?: boolean; // default false
active?:boolean; // default false
}
export interface ITabAttributes {
altName?: string;
Expand Down
13 changes: 9 additions & 4 deletions src/model/Model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,16 @@ export class Model {
const attributeDefinitions = new AttributeDefinitions();

attributeDefinitions.add("legacyOverflowMenu", false).setType(Attribute.BOOLEAN);

// splitter
attributeDefinitions.add("splitterSize", -1).setType(Attribute.NUMBER);
attributeDefinitions.add("splitterExtra", 0).setType(Attribute.NUMBER);
attributeDefinitions.add("enableEdgeDock", true).setType(Attribute.BOOLEAN);
attributeDefinitions.add("rootOrientationVertical", false).setType(Attribute.BOOLEAN);
attributeDefinitions.add("marginInsets", { top: 0, right: 0, bottom: 0, left: 0 })
.setType("IInsets");
attributeDefinitions.add("enableUseVisibility", false).setType(Attribute.BOOLEAN);
attributeDefinitions.add("enableRotateBorderIcons", true).setType(Attribute.BOOLEAN);

// splitter
attributeDefinitions.add("splitterSize", -1).setType(Attribute.NUMBER);
attributeDefinitions.add("splitterExtra", 0).setType(Attribute.NUMBER);

// tab
attributeDefinitions.add("tabEnableClose", true).setType(Attribute.BOOLEAN);
Expand Down Expand Up @@ -207,6 +208,10 @@ export class Model {
return this._attributes.enableUseVisibility as boolean;
}

isEnableRotateBorderIcons() {
return this._attributes.enableRotateBorderIcons as boolean;
}

/**
* Gets the
* @returns {BorderSet|*}
Expand Down
11 changes: 10 additions & 1 deletion src/view/BorderButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,16 @@ export const BorderButton = (props: IBorderButtonProps) => {
classNames += " " + node.getClassName();
}

const renderState = getRenderStateEx(layout, node, iconFactory, titleFactory);
let iconAngle = 0;
if (node.getModel().isEnableRotateBorderIcons() === false) {
if (border === "left") {
iconAngle = 90;
} else if (border === "right") {
iconAngle = -90;
}
}

const renderState = getRenderStateEx(layout, node, iconFactory, titleFactory, iconAngle);

let content = renderState.content ? (
<div className={cm(CLASSES.FLEXLAYOUT__BORDER_BUTTON_CONTENT)}>
Expand Down
44 changes: 24 additions & 20 deletions src/view/BorderTabSet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { DockLocation } from "../DockLocation";
import { BorderNode } from "../model/BorderNode";
import { TabNode } from "../model/TabNode";
import { BorderButton } from "./BorderButton";
import { IIcons, ILayoutCallbacks, ITitleObject } from "./Layout";
import { IIcons, ILayoutCallbacks, ITabSetRenderValues, ITitleObject } from "./Layout";
import { showPopup } from "../PopupMenu";
import { Actions } from "../model/Actions";
import { I18nLabel } from "../I18nLabel";
Expand Down Expand Up @@ -117,9 +117,30 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
// allow customization of tabset right/bottom buttons
let buttons: any[] = [];
let stickyButtons: any[] = [];
const renderState = { headerContent: undefined, buttons, stickyButtons: stickyButtons, headerButtons: [] };
const renderState : ITabSetRenderValues= { headerContent: undefined, buttons, stickyButtons: stickyButtons, headerButtons: [], overflowPosition: undefined };
layout.customizeTabSet(border, renderState);
buttons = renderState.buttons;

if (renderState.overflowPosition === undefined) {
renderState.overflowPosition = stickyButtons.length;
}

if (stickyButtons.length > 0) {
if (tabsTruncated) {
buttons = [...stickyButtons, ...buttons];
} else {
tabs.push(<div
ref={stickyButtonsRef}
key="sticky_buttons_container"
onMouseDown={onInterceptMouseDown}
onTouchStart={onInterceptMouseDown}
onDragStart={(e) => { e.preventDefault() }}
className={cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR_STICKY_BUTTONS_CONTAINER)}
>
{stickyButtons}
</div>);
}
}

if (hiddenTabs.length > 0) {
const overflowTitle = layout.i18nName(I18nLabel.Overflow_Menu_Tooltip);
Expand All @@ -132,7 +153,7 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
<div className={cm(CLASSES.FLEXLAYOUT__TAB_BUTTON_OVERFLOW_COUNT)}>{hiddenTabs.length}</div>
</>);
}
buttons.unshift(
buttons.splice(Math.min(renderState.overflowPosition, buttons.length), 0,
<button
key="overflowbutton"
ref={overflowbuttonRef}
Expand All @@ -146,23 +167,6 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
</button>
);
}

if (stickyButtons.length > 0) {
if (tabsTruncated) {
buttons = [...stickyButtons, ...buttons];
} else {
tabs.push(<div
ref={stickyButtonsRef}
key="sticky_buttons_container"
onMouseDown={onInterceptMouseDown}
onTouchStart={onInterceptMouseDown}
onDragStart={(e) => { e.preventDefault() }}
className={cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR_STICKY_BUTTONS_CONTAINER)}
>
{stickyButtons}
</div>);
}
}

const selectedIndex = border.getSelected();
if (selectedIndex !== -1) {
Expand Down
15 changes: 9 additions & 6 deletions src/view/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ export interface ITabSetRenderValues {
stickyButtons: React.ReactNode[];
buttons: React.ReactNode[];
headerButtons: React.ReactNode[];
// position to insert overflow button within [...stickyButtons, ...buttons]
// if left undefined position will be after the sticky buttons (if any)
overflowPosition: number | undefined;
}

export interface ITabRenderValues {
Expand Down Expand Up @@ -510,10 +513,10 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
const offset = this.edgeRectLength / 2;
const className = this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT);
const radius = 50;
edges.push(<div key="North" style={{ top: r.y, left: r.x + r.width / 2 - offset, width: length, height: width, borderBottomLeftRadius: radius, borderBottomRightRadius: radius }} className={className}></div>)
edges.push(<div key="West" style={{ top: r.y + r.height / 2 - offset, left: r.x, width: width, height: length, borderTopRightRadius: radius, borderBottomRightRadius: radius }} className={className}></div>)
edges.push(<div key="South" style={{ top: r.y + r.height - width, left: r.x + r.width / 2 - offset, width: length, height: width, borderTopLeftRadius: radius, borderTopRightRadius: radius }} className={className}></div>)
edges.push(<div key="East" style={{ top: r.y + r.height / 2 - offset, left: r.x + r.width - width, width: width, height: length, borderTopLeftRadius: radius, borderBottomLeftRadius: radius }} className={className}></div>)
edges.push(<div key="North" style={{ top: r.y, left: r.x + r.width / 2 - offset, width: length, height: width, borderBottomLeftRadius: radius, borderBottomRightRadius: radius }} className={className + " " + this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT_TOP)}></div>);
edges.push(<div key="West" style={{ top: r.y + r.height / 2 - offset, left: r.x, width: width, height: length, borderTopRightRadius: radius, borderBottomRightRadius: radius }} className={className + " " + this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT_LEFT)}></div>);
edges.push(<div key="South" style={{ top: r.y + r.height - width, left: r.x + r.width / 2 - offset, width: length, height: width, borderTopLeftRadius: radius, borderTopRightRadius: radius }} className={className + " " + this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT_BOTTOM)}></div>);
edges.push(<div key="East" style={{ top: r.y + r.height / 2 - offset, left: r.x + r.width - width, width: width, height: length, borderTopLeftRadius: radius, borderBottomLeftRadius: radius }} className={className + " " + this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT_RIGHT)}></div>);
}

// this.layoutTime = (Date.now() - this.start);
Expand Down Expand Up @@ -596,8 +599,8 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
if (this.supportsPopout && child.isFloating()) {
const rect = this._getScreenRect(child);

const tabBorderWidth= child._getAttr("borderWidth");
const tabBorderHeight= child._getAttr("borderHeight");
const tabBorderWidth = child._getAttr("borderWidth");
const tabBorderHeight = child._getAttr("borderHeight");
if (tabBorderWidth !== -1 && border.getLocation().getOrientation() === Orientation.HORZ) {
rect.width = tabBorderWidth;
} else if (tabBorderHeight !== -1 && border.getLocation().getOrientation() === Orientation.VERT) {
Expand Down
44 changes: 24 additions & 20 deletions src/view/TabSet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Actions } from "../model/Actions";
import { TabNode } from "../model/TabNode";
import { TabSetNode } from "../model/TabSetNode";
import { showPopup } from "../PopupMenu";
import { IIcons, ILayoutCallbacks, ITitleObject } from "./Layout";
import { IIcons, ILayoutCallbacks, ITabSetRenderValues, ITitleObject } from "./Layout";
import { TabButton } from "./TabButton";
import { useTabOverflow } from "./TabOverflowHook";
import { Orientation } from "../Orientation";
Expand Down Expand Up @@ -160,13 +160,34 @@ export const TabSet = (props: ITabSetProps) => {
let headerButtons: React.ReactNode[] = [];

// allow customization of header contents and buttons
const renderState = { headerContent: node.getName(), stickyButtons, buttons, headerButtons };
const renderState : ITabSetRenderValues = { headerContent: node.getName(), stickyButtons, buttons, headerButtons, overflowPosition: undefined };
layout.customizeTabSet(node, renderState);
const headerContent = renderState.headerContent;
stickyButtons = renderState.stickyButtons;
buttons = renderState.buttons;
headerButtons = renderState.headerButtons;

if (renderState.overflowPosition === undefined) {
renderState.overflowPosition = stickyButtons.length;
}

if (stickyButtons.length > 0) {
if (tabsTruncated) {
buttons = [...stickyButtons, ...buttons];
} else {
tabs.push(<div
ref={stickyButtonsRef}
key="sticky_buttons_container"
onMouseDown={onInterceptMouseDown}
onTouchStart={onInterceptMouseDown}
onDragStart={(e) => { e.preventDefault() }}
className={cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR_STICKY_BUTTONS_CONTAINER)}
>
{stickyButtons}
</div>);
}
}

if (hiddenTabs.length > 0) {
const overflowTitle = layout.i18nName(I18nLabel.Overflow_Menu_Tooltip);
let overflowContent;
Expand All @@ -178,7 +199,7 @@ export const TabSet = (props: ITabSetProps) => {
<div className={cm(CLASSES.FLEXLAYOUT__TAB_BUTTON_OVERFLOW_COUNT)}>{hiddenTabs.length}</div>
</>);
}
buttons.unshift(
buttons.splice(Math.min(renderState.overflowPosition, buttons.length), 0,
<button
key="overflowbutton"
data-layout-path={path + "/button/overflow"}
Expand All @@ -195,23 +216,6 @@ export const TabSet = (props: ITabSetProps) => {
);
}

if (stickyButtons.length > 0) {
if (tabsTruncated) {
buttons = [...stickyButtons, ...buttons];
} else {
tabs.push(<div
ref={stickyButtonsRef}
key="sticky_buttons_container"
onMouseDown={onInterceptMouseDown}
onTouchStart={onInterceptMouseDown}
onDragStart={(e) => { e.preventDefault() }}
className={cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR_STICKY_BUTTONS_CONTAINER)}
>
{stickyButtons}
</div>);
}
}

if (selectedTabNode !== undefined && layout.isSupportsPopout() && selectedTabNode.isEnableFloat() && !selectedTabNode.isFloating()) {
const floatTitle = layout.i18nName(I18nLabel.Float_Tab);
buttons.push(
Expand Down
12 changes: 10 additions & 2 deletions src/view/Utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ export function getRenderStateEx(
layout: ILayoutCallbacks,
node: TabNode,
iconFactory?: IconFactory,
titleFactory?: TitleFactory
titleFactory?: TitleFactory,
iconAngle?: number
) {
let leadingContent = iconFactory ? iconFactory(node) : undefined;
let titleContent: React.ReactNode = node.getName();
let name = node.getName();
if (iconAngle === undefined) {
iconAngle = 0;
}

function isTitleObject(obj: any): obj is ITitleObject {
return obj.titleContent !== undefined
Expand All @@ -33,7 +37,11 @@ export function getRenderStateEx(
}

if (leadingContent === undefined && node.getIcon() !== undefined) {
leadingContent = <img style={{ width: "1em", height: "1em" }} src={node.getIcon()} alt="leadingContent" />;
if (iconAngle !== 0) {
leadingContent = <img style={{ width: "1em", height: "1em", transform: "rotate(" + iconAngle + "deg)" }} src={node.getIcon()} alt="leadingContent" />;
} else {
leadingContent = <img style={{ width: "1em", height: "1em" }} src={node.getIcon()} alt="leadingContent" />;
}
}

let buttons: any[] = [];
Expand Down

0 comments on commit 82ce11c

Please sign in to comment.