From 4d9496f40fae758c0fdf2ce0f6ff2cd375414ce7 Mon Sep 17 00:00:00 2001 From: Jeremy Magland Date: Fri, 26 Apr 2024 09:28:42 -0400 Subject: [PATCH] vertical tab widget layout --- gui/package.json | 2 +- .../component-tab-widget/TabWidget.tsx | 99 ++++++++++++++++++- .../component-tab-widget/TabWidgetTabBar.tsx | 10 +- .../view-main-layout/MainLayoutViewData.ts | 4 +- .../view-main-layout/TabLayoutItemView.tsx | 1 + sortingview/views/TabLayout.py | 9 +- 6 files changed, 113 insertions(+), 12 deletions(-) diff --git a/gui/package.json b/gui/package.json index 78d9d332..c8aa3443 100644 --- a/gui/package.json +++ b/gui/package.json @@ -1,7 +1,7 @@ { "name": "@fi-sci/figurl-sortingview", "private": false, - "version": "12.0.4", + "version": "12.0.6", "scripts": { "dev": "vite --port 3000", "build": "tsc && vite build && node devel/generate_file_manifest.js", diff --git a/gui/src/libraries/core-views/component-tab-widget/TabWidget.tsx b/gui/src/libraries/core-views/component-tab-widget/TabWidget.tsx index 1a8f7cff..8361aac6 100644 --- a/gui/src/libraries/core-views/component-tab-widget/TabWidget.tsx +++ b/gui/src/libraries/core-views/component-tab-widget/TabWidget.tsx @@ -5,6 +5,7 @@ type Props = { tabs: { label: string }[] + tabBarLayout?: 'horizontal' | 'vertical' width: number height: number } @@ -12,7 +13,38 @@ type Props = { // needs to correspond to css (not best system) - see mountainview.css const tabBarHeight = 30 + 5 -const TabWidget: FunctionComponent> = ({children, tabs, width, height}) => { +const TabWidget: FunctionComponent> = ({children, tabs, tabBarLayout, width, height}) => { + const tbl = tabBarLayout || 'horizontal' + if (tbl === 'horizontal') { + return ( + + {children} + + ) + } + else if (tbl === 'vertical') { + return ( + + {children} + + ) + } + else { + return
TabWidget: unknown tabBarLayout {tbl}
+ } +} + +const TabWidgetHorizontal: FunctionComponent> = ({children, tabs, tabBarLayout, width, height}) => { const [currentTabIndex, setCurrentTabIndex] = useState(undefined) const children2 = children as React.ReactElement[] if ((children2 || []).length !== tabs.length) { @@ -32,7 +64,7 @@ const TabWidget: FunctionComponent> = ({children, tabs, tabs={tabs} currentTabIndex={currentTabIndex} onCurrentTabIndexChanged={setCurrentTabIndex} - onTabClosed={() => {}} + onTabClosed={undefined} /> { @@ -49,4 +81,67 @@ const TabWidget: FunctionComponent> = ({children, tabs, ) } +const TabWidgetVertical: FunctionComponent> = ({children, tabs, tabBarLayout, width, height}) => { + const [currentTabIndex, setCurrentTabIndex] = useState(0) + const children2 = children as React.ReactElement[] + if ((children2 || []).length !== tabs.length) { + throw Error('TabWidget: incorrect number of tabs') + } + const leftPanelWidth = Math.min(250, width / 3) + const W = width - leftPanelWidth + const H = height + return ( +
+
+ +
+
+ { + children2.map((c, i) => { + const visible = i === currentTabIndex + return ( +
+ +
+ ) + }) + } +
+
+ ) +} + +type VerticalTabSelectionPanelProps = { + tabs: { + label: string + }[] + currentTabIndex?: number + onCurrentTabIndexChanged: (i: number) => void + width: number + height: number +} + +const VerticalTabSelectionPanel: FunctionComponent = ({tabs, currentTabIndex, onCurrentTabIndexChanged, width, height}) => { + return ( +
+ { + tabs.map((tab, i) => ( +
onCurrentTabIndexChanged(i)}> + {tab.label} +
+ )) + } +
+ ) +} + export default TabWidget \ No newline at end of file diff --git a/gui/src/libraries/core-views/component-tab-widget/TabWidgetTabBar.tsx b/gui/src/libraries/core-views/component-tab-widget/TabWidgetTabBar.tsx index 3de7a5e5..772a368c 100644 --- a/gui/src/libraries/core-views/component-tab-widget/TabWidgetTabBar.tsx +++ b/gui/src/libraries/core-views/component-tab-widget/TabWidgetTabBar.tsx @@ -9,7 +9,7 @@ type Props = { }[] currentTabIndex: number | undefined onCurrentTabIndexChanged: (i: number) => void - onTabClosed: (i: number) => void + onTabClosed?: (i: number) => void } const TabWidgetTabBar: FunctionComponent = ({ tabs, currentTabIndex, onCurrentTabIndexChanged, onTabClosed }) => { @@ -53,7 +53,7 @@ const TabWidgetTabBar: FunctionComponent = ({ tabs, currentTabIndex, onCu type TabProps = { tab: {label: string} tabIndex: number - onClose: (i: number) => void + onClose?: (i: number) => void opts: {selected?: boolean} onClick: (i: number) => void } @@ -75,7 +75,7 @@ const TabWidgetTab: FunctionComponent = ({tab, onClose, opts, onClick, {} {tab.label}   - onClose(tabIndex)} className="CloseButton" @@ -88,12 +88,12 @@ const TabWidgetTab: FunctionComponent = ({tab, onClose, opts, onClick, fontSize: 20 }} /> - + : } ) const style: React.CSSProperties = useMemo(() => (opts.selected ? {color: 'black', fontWeight: 'bold'} : {color: 'gray'}), [opts.selected]) return ( - + ) } diff --git a/gui/src/libraries/core-views/view-main-layout/MainLayoutViewData.ts b/gui/src/libraries/core-views/view-main-layout/MainLayoutViewData.ts index ae91369d..825f63f8 100644 --- a/gui/src/libraries/core-views/view-main-layout/MainLayoutViewData.ts +++ b/gui/src/libraries/core-views/view-main-layout/MainLayoutViewData.ts @@ -36,6 +36,7 @@ export type LayoutItem = { } | { type: 'TabLayout' items: LayoutItem[] + tabBarLayout?: 'horizontal' | 'vertical' itemProperties: { label: string }[] @@ -86,7 +87,8 @@ export const isLayoutItem = (x: any): x is LayoutItem => { items: isArrayOf(isLayoutItem), itemProperties: isArrayOf(z => (validateObject(z, { label: isString - }))) + }))), + tabBarLayout: optional(isOneOf(['horizontal', 'vertical'].map(s => (isEqualTo(s))))) })), (y: any) => (validateObject(y, { type: isEqualTo('View'), diff --git a/gui/src/libraries/core-views/view-main-layout/TabLayoutItemView.tsx b/gui/src/libraries/core-views/view-main-layout/TabLayoutItemView.tsx index dedc8bd1..b075bc7d 100644 --- a/gui/src/libraries/core-views/view-main-layout/TabLayoutItemView.tsx +++ b/gui/src/libraries/core-views/view-main-layout/TabLayoutItemView.tsx @@ -29,6 +29,7 @@ const TabLayoutItemView: FunctionComponent = ({layoutItem, ViewComponent, tabs={tabs} width={width} height={height} + tabBarLayout={layoutItem.tabBarLayout} > { items.map((item, ii) => ( diff --git a/sortingview/views/TabLayout.py b/sortingview/views/TabLayout.py index f0a0d968..52b3e738 100644 --- a/sortingview/views/TabLayout.py +++ b/sortingview/views/TabLayout.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, Literal from .View import View @@ -13,16 +13,19 @@ class TabLayout(View): Tab layout """ - def __init__(self, items: List[TabLayoutItem], **kwargs) -> None: + def __init__(self, items: List[TabLayoutItem], tab_bar_layout: Literal['horizontal', 'vertical'] = 'horizontal', **kwargs) -> None: super().__init__("TabLayout", is_layout=True, **kwargs) self._items = items + self._tab_bar_layout = tab_bar_layout def to_dict(self) -> dict: ret = { "type": self.type, "items": [item.view.to_dict() if item.view.is_layout else {"type": "View", "viewId": item.view.id} for item in self._items], - "itemProperties": [{"label": item.label} for item in self._items], + "itemProperties": [{"label": item.label} for item in self._items] } + if self._tab_bar_layout != "horizontal": + ret["tabBarLayout"] = self._tab_bar_layout return ret def child_views(self) -> List[View]: