From 8fcf7cf732b7394c3414caf266996c2ed7898e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Loi=CC=88c=20Correnson?= <loic.correnson@cea.fr> Date: Sun, 10 Jan 2021 15:15:54 +0100 Subject: [PATCH] [ivette] move LabView API in ivette --- ivette/src/ivette/index.tsx | 173 +++++++++++++++++++++++++++ ivette/src/renderer/Application.tsx | 3 +- ivette/src/renderer/LabView.tsx | 176 +++------------------------- ivette/tsconfig.json | 3 +- ivette/webpack.renderer.js | 3 +- 5 files changed, 194 insertions(+), 164 deletions(-) create mode 100644 ivette/src/ivette/index.tsx diff --git a/ivette/src/ivette/index.tsx b/ivette/src/ivette/index.tsx new file mode 100644 index 00000000000..e51739eedcd --- /dev/null +++ b/ivette/src/ivette/index.tsx @@ -0,0 +1,173 @@ +// -------------------------------------------------------------------------- +// --- Lab View Component +// -------------------------------------------------------------------------- + +/** + @packageDocumentation + @module ivette + */ + +import React from 'react'; +import { Label } from 'dome/controls/labels'; +import { DefineElement } from 'dome/layout/dispatch'; +import { + Rankify, + useGroupContext, + useLibraryItem, + useTitleContext, +} from 'ivette@lab'; + +/* --------------------------------------------------------------------------*/ +/* --- Fragments ---*/ +/* --------------------------------------------------------------------------*/ + +export interface FragmentProps { + group?: string; + rank?: number; + children?: React.ReactNode; +} + +/** + Ordered collection of LabView Components. + Otherwise, elements are ordered by `rank` and `id`. + */ +export function Fragment(props: FragmentProps) { + const { group, rank, children } = props; + const context = useGroupContext(); + const base = context.order ?? []; + return ( + <Rankify + group={group ?? context.group} + order={rank === undefined ? base : [...base, rank]} + > + {children} + </Rankify> + ); +} + +/* --------------------------------------------------------------------------*/ +/* --- Groups ---*/ +/* --------------------------------------------------------------------------*/ + +export interface ItemProps { + /** Identifier. */ + id: string; + /** Displayed name. */ + label: string; + /** Tooltip description. */ + title?: string; + /** Contents. */ + children?: React.ReactNode; +} + +/** + Defines a group of components. The components rendered + _inside_ its content are implicitely affected to this group, + unless specified. The group content are also rendered + in their specified order. For nested collections of components, + use `<Fragment/>` instead of `<React.Fragment/>` to specify order. + */ +export function Group(props: ItemProps) { + const { children, ...group } = props; + const context = useLibraryItem('groups', group); + return ( + <Rankify + group={props.id} + order={context.order ?? []} + > + {children} + </Rankify> + ); +} + +// -------------------------------------------------------------------------- +// --- Views +// -------------------------------------------------------------------------- + +export interface ViewProps extends ItemProps { + /** Use this view by default. */ + defaultView?: boolean; +} + +/** + Layout of LabView Components. + Defines a predefined layout of components. The view is organized + into a GridContent, which must _only_ consists of: + - `<GridHbox>…</GridHbox>` an horizontal grid of `GridContent` elements; + - `<GridVbox>…</GridVbox>` a vertical grid of `GridContent` elements; + - `<GridItem id=…>` a single component. + + These grid content components must be imported from the `dome/layout/grids` + module: + ``` + import { GridItem, GridHbox, GridVbox } from 'dome/layout/grids'; + ``` + */ +export function View(props: ViewProps) { + useLibraryItem('views', props); + return null; +} + +// -------------------------------------------------------------------------- +// --- Components +// -------------------------------------------------------------------------- + +export interface ComponentProps extends ItemProps { + /** Group attachment (defaults to group context) */ + group?: string; + /** Ordering index (defaults to fragment context). */ + rank?: number; +} + +/** + LabView Component. + Defines a component and its content when incorporated inside a view. + Unless specified, the component will be implicitely attached + to the current enclosing group. The `rank` property can be used + for adjusting component ordering (see also `<Fragment/>` and `<Group/>`). + */ +export function Component(props: ComponentProps) { + useLibraryItem('components', props); + return null; +} + +export interface TitleBarProps { + /* + @property {string} [icon] - displayed icon + @property {string} [label] - displayed name + @property {string} [title] - description tooltip + @property {React.Children} children - additional components to render + */ + /** Displayed icon. */ + icon?: string; + /** Displayed name (when mounted). */ + label?: string; + /** Tooltip description (when mounted). */ + title?: string; + /** TitleBar additional components (stacked to right). */ + children?: React.ReactNode; +} + +/** + LabView Component's title bar. + Defines an alternative component title bar in current context. + Default values are taken from the associated component. + */ +export function TitleBar(props: TitleBarProps) { + const { icon, label, title, children } = props; + const context = useTitleContext(); + if (!context.id) return null; + return ( + <DefineElement id={`labview.title.${context.id}`}> + <Label + className="labview-handle" + icon={icon} + label={label || context.label} + title={title || context.title} + /> + {children} + </DefineElement> + ); +} + +// -------------------------------------------------------------------------- diff --git a/ivette/src/renderer/Application.tsx b/ivette/src/renderer/Application.tsx index 39f1c56396c..46f82f8a42b 100644 --- a/ivette/src/renderer/Application.tsx +++ b/ivette/src/renderer/Application.tsx @@ -15,7 +15,8 @@ import { GridHbox, GridItem } from 'dome/layout/grids'; // --- Frama-C Plugins -import { LabView, View, Group } from 'ivette'; +import { LabView } from 'ivette@lab'; +import { View, Group } from 'ivette'; import Values from 'frama-c/eva/Values'; import Dive from 'frama-c/dive/Dive'; diff --git a/ivette/src/renderer/LabView.tsx b/ivette/src/renderer/LabView.tsx index dcd5f2a8457..ec68ab541ca 100644 --- a/ivette/src/renderer/LabView.tsx +++ b/ivette/src/renderer/LabView.tsx @@ -2,11 +2,6 @@ // --- Lab View Component // -------------------------------------------------------------------------- -/** - @packageDocumentation - @module ivette -*/ - import _ from 'lodash'; import React from 'react'; import * as Dome from 'dome'; @@ -21,7 +16,7 @@ import { Hbox, Hfill, Vfill } from 'dome/layout/boxes'; import { IconButton, Field } from 'dome/controls/buttons'; import { Label } from 'dome/controls/labels'; import { Icon } from 'dome/controls/icons'; -import { DefineElement, RenderElement } from 'dome/layout/dispatch'; +import { RenderElement } from 'dome/layout/dispatch'; import './style-labview.css'; @@ -125,7 +120,14 @@ interface GroupContext { const GROUP = React.createContext<GroupContext>({}); -function useLibraryItem(fd: string, { id, ...props }: any): GroupContext { +export function useGroupContext() { + return React.useContext(GROUP); +} + +export function useLibraryItem( + fd: string, + { id, ...props }: any, +): GroupContext { const context = React.useContext(GROUP); React.useEffect(() => { const { group, order } = context; @@ -140,13 +142,13 @@ function useLibraryItem(fd: string, { id, ...props }: any): GroupContext { /* --- Rankifyier ---*/ /* --------------------------------------------------------------------------*/ -interface RankifyProps { +export interface RankifyProps { group: string | undefined; order: number[] | undefined; children: React.ReactNode | undefined; } -function Rankify(props: RankifyProps) { +export function Rankify(props: RankifyProps) { const { group, order = [], children } = props; let rank = 0; const rankify = (elt: any) => { @@ -174,170 +176,22 @@ function UseLibrary(props: { children?: React.ReactNode }) { ); } -/* --------------------------------------------------------------------------*/ -/* --- Fragments ---*/ -/* --------------------------------------------------------------------------*/ - -export interface FragmentProps { - group?: string; - rank?: number; - children?: React.ReactNode; -} - -/** - Ordered collection of LabView Components. - Otherwise, elements are ordered by `rank` and `id`. - */ -export function Fragment(props: FragmentProps) { - const { group, rank, children } = props; - const context = React.useContext(GROUP); - const base = context.order ?? []; - return ( - <Rankify - group={group ?? context.group} - order={rank === undefined ? base : [...base, rank]} - > - {children} - </Rankify> - ); -} - -/* --------------------------------------------------------------------------*/ -/* --- Groups ---*/ -/* --------------------------------------------------------------------------*/ - -export interface ItemProps { - /** Identifier. */ - id: string; - /** Displayed name. */ - label: string; - /** Tooltip description. */ - title?: string; - /** Contents. */ - children?: React.ReactNode; -} - -/** - Defines a group of components. The components rendered - _inside_ its content are implicitely affected to this group, - unless specified. The group content are also rendered - in their specified order. For nested collections of components, - use `<Fragment/>` instead of `<React.Fragment/>` to specify order. - */ -export function Group(props: ItemProps) { - const { children, ...group } = props; - const context = useLibraryItem('groups', group); - return ( - <Rankify - group={props.id} - order={context.order ?? []} - > - {children} - </Rankify> - ); -} - // -------------------------------------------------------------------------- -// --- Views -// -------------------------------------------------------------------------- - -export interface ViewProps extends ItemProps { - /** Use this view by default. */ - defaultView?: boolean; -} - -/** - Layout of LabView Components. - Defines a predefined layout of components. The view is organized - into a GridContent, which must _only_ consists of: - - `<GridHbox>…</GridHbox>` an horizontal grid of `GridContent` elements; - - `<GridVbox>…</GridVbox>` a vertical grid of `GridContent` elements; - - `<GridItem id=…>` a single component. - - These grid content components must be imported from the `dome/layout/grids` - module: - ``` - import { GridItem, GridHbox, GridVbox } from 'dome/layout/grids'; - ``` - */ -export function View(props: ViewProps) { - useLibraryItem('views', props); - return null; -} - -// -------------------------------------------------------------------------- -// --- Components +// --- Grid Item // -------------------------------------------------------------------------- -export interface ComponentProps extends ItemProps { - /** Group attachment (defaults to group context) */ - group?: string; - /** Ordering index (defaults to fragment context). */ - rank?: number; -} - -/** - LabView Component. - Defines a component and its content when incorporated inside a view. - Unless specified, the component will be implicitely attached - to the current enclosing group. The `rank` property can be used - for adjusting component ordering (see also `<Fragment/>` and `<Group/>`). - */ -export function Component(props: ComponentProps) { - useLibraryItem('components', props); - return null; -} - interface TitleContext { id?: string; label?: string; title?: string; } + const TITLE = React.createContext<TitleContext>({}); -export interface TitleBarProps { - /* - @property {string} [icon] - displayed icon - @property {string} [label] - displayed name - @property {string} [title] - description tooltip - @property {React.Children} children - additional components to render - */ - /** Displayed icon. */ - icon?: string; - /** Displayed name (when mounted). */ - label?: string; - /** Tooltip description (when mounted). */ - title?: string; - /** TitleBar additional components (stacked to right). */ - children?: React.ReactNode; +export function useTitleContext() { + return React.useContext(TITLE); } -/** - LabView Component's title bar. - Defines an alternative component title bar in current context. - Default values are taken from the associated component. - */ -export const TitleBar = ({ icon, label, title, children }: any) => { - const context = React.useContext(TITLE); - const { id } = context; - if (!id) return null; - return ( - <DefineElement id={`labview.title.${id}`}> - <Label - className="labview-handle" - icon={icon} - label={label || context.label} - title={title || context.title} - /> - {children} - </DefineElement> - ); -}; - -// -------------------------------------------------------------------------- -// --- Grid Item -// -------------------------------------------------------------------------- - const GRIDITEM = { className: 'dome-container dome-xBoxes-vbox dome-xBoxes-box', handle: '.labview-handle', diff --git a/ivette/tsconfig.json b/ivette/tsconfig.json index 6107a85a5aa..3258d0eb1e0 100644 --- a/ivette/tsconfig.json +++ b/ivette/tsconfig.json @@ -43,7 +43,8 @@ "resolveJsonModule": true, /* Allow to load JSON files as module. */ "baseUrl": ".", /* Base directory to resolve non-absolute module names. */ "paths": { /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - "ivette": [ "src/renderer/LabView.tsx" ], + "ivette@lab": [ "src/renderer/LabView.tsx" ], + "ivette": [ "src/ivette" ], "frama-c/api/*": [ "api/generated/*" ], "frama-c/*": [ "src/frama-c/*" ], "dome": [ "src/dome/renderer/dome.tsx" ], diff --git a/ivette/webpack.renderer.js b/ivette/webpack.renderer.js index 515c836cde5..0f02136b60b 100644 --- a/ivette/webpack.renderer.js +++ b/ivette/webpack.renderer.js @@ -29,7 +29,8 @@ module.exports = { alias: { 'frama-c/api': path.resolve( __dirname , 'api/generated' ), 'frama-c': path.resolve( __dirname , 'src/frama-c' ), - 'ivette': path.resolve( __dirname , 'src/renderer/LabView' ), + 'ivette@lab': path.resolve( __dirname , 'src/renderer/LabView' ), + 'ivette': path.resolve( __dirname , 'src/ivette' ), 'dome/misc': path.resolve( DOME , 'misc' ), 'dome/system': path.resolve( DOME , 'misc/system.ts' ), 'dome$': path.resolve( DOME , 'renderer/dome.tsx' ), -- GitLab