From 47e3c973fb6a7eca232cbe5356291f95cf4e7e99 Mon Sep 17 00:00:00 2001 From: MrKBear Date: Tue, 8 Mar 2022 17:36:26 +0800 Subject: [PATCH 1/6] Add toggles input component --- .../Component/TogglesInput/TogglesInput.scss | 63 +++++++++++++++++++ .../Component/TogglesInput/TogglesInput.tsx | 45 +++++++++++++ source/Localization/EN-US.ts | 1 + source/Localization/ZH-CN.ts | 1 + source/Panel/RangeDetails/RangeDetails.tsx | 28 ++++++--- 5 files changed, 129 insertions(+), 9 deletions(-) create mode 100644 source/Component/TogglesInput/TogglesInput.scss create mode 100644 source/Component/TogglesInput/TogglesInput.tsx diff --git a/source/Component/TogglesInput/TogglesInput.scss b/source/Component/TogglesInput/TogglesInput.scss new file mode 100644 index 0000000..88598f9 --- /dev/null +++ b/source/Component/TogglesInput/TogglesInput.scss @@ -0,0 +1,63 @@ +@import "../Theme/Theme.scss"; + +$line-min-height: 26px; + +div.toggles-input { + width: 100%; + display: flex; + min-height: $line-min-height; + padding: 5px 0; + + div.toggles-intro { + width: 50%; + height: 100%; + max-width: 220px; + display: flex; + align-items: center; + padding-right: 5px; + box-sizing: border-box; + } + + div.toggles-content { + width: 50%; + height: 100%; + max-width: 180px; + min-height: $line-min-height; + + div.checkbox { + width: $line-min-height; + height: $line-min-height; + overflow: hidden; + border-radius: 3px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + user-select: none; + } + } +} + +div.dark.toggles-input { + + div.toggles-content div.checkbox { + background-color: $lt-bg-color-lvl3-dark; + color: $lt-font-color-normal-dark; + } + + div.toggles-content div.checkbox:hover { + background-color: $lt-bg-color-lvl2-dark; + } +} + +div.light.toggles-input { + + div.toggles-content div.checkbox { + background-color: $lt-bg-color-lvl3-light; + color: $lt-font-color-normal-light; + } + + div.toggles-content div.checkbox:hover { + background-color: $lt-bg-color-lvl2-light; + } +} \ No newline at end of file diff --git a/source/Component/TogglesInput/TogglesInput.tsx b/source/Component/TogglesInput/TogglesInput.tsx new file mode 100644 index 0000000..0aa21c6 --- /dev/null +++ b/source/Component/TogglesInput/TogglesInput.tsx @@ -0,0 +1,45 @@ +import { AllI18nKeys, Localization } from "@Component/Localization/Localization"; +import { Theme } from "@Component/Theme/Theme"; +import { Icon } from "@fluentui/react"; +import { Component, ReactNode } from "react"; +import "./TogglesInput.scss"; + +interface ITogglesInputProps { + keyI18n: AllI18nKeys; + infoI18n?: AllI18nKeys; + value?: boolean; + disable?: boolean; + valueChange?: (color: boolean) => any; +} + +class TogglesInput extends Component { + public render(): ReactNode { + return +
+ +
+
+
{ + if (this.props.disable) { + return; + } + if (this.props.valueChange) { + this.props.valueChange(!this.props.value); + } + })} + > + +
+
+
+ } +} + +export { TogglesInput }; \ No newline at end of file diff --git a/source/Localization/EN-US.ts b/source/Localization/EN-US.ts index 2ab0d8c..752c7a2 100644 --- a/source/Localization/EN-US.ts +++ b/source/Localization/EN-US.ts @@ -42,6 +42,7 @@ const EN_US = { "Common.Attr.Key.Radius.Y": "Radius Y", "Common.Attr.Key.Radius.Z": "Radius Z", "Common.Attr.Key.Color": "Color", + "Common.Attr.Key.Display": "Display", "Common.Attr.Key.Error.Multiple": "Multiple values", "Panel.Info.Range.Details.Attr.Error.Not.Range": "Object is not a Range", "Panel.Info.Range.Details.Attr.Error.Unspecified": "Unspecified range object", diff --git a/source/Localization/ZH-CN.ts b/source/Localization/ZH-CN.ts index 80753da..dfa4c99 100644 --- a/source/Localization/ZH-CN.ts +++ b/source/Localization/ZH-CN.ts @@ -42,6 +42,7 @@ const ZH_CN = { "Common.Attr.Key.Radius.Y": "Y 半径", "Common.Attr.Key.Radius.Z": "Z 半径", "Common.Attr.Key.Color": "颜色", + "Common.Attr.Key.Display": "显示", "Common.Attr.Key.Error.Multiple": "多重数值", "Panel.Info.Range.Details.Attr.Error.Not.Range": "对象不是一个范围", "Panel.Info.Range.Details.Attr.Error.Unspecified": "未指定范围对象", diff --git a/source/Panel/RangeDetails/RangeDetails.tsx b/source/Panel/RangeDetails/RangeDetails.tsx index 4fe9548..8f0ac55 100644 --- a/source/Panel/RangeDetails/RangeDetails.tsx +++ b/source/Panel/RangeDetails/RangeDetails.tsx @@ -5,6 +5,7 @@ import { AllI18nKeys } from "@Component/Localization/Localization"; import { Range } from "@Model/Range"; import { ObjectID } from "@Model/Renderer"; import { ColorInput } from "@Component/ColorInput/ColorInput"; +import { TogglesInput } from "@Component/TogglesInput/TogglesInput"; import "./RangeDetails.scss"; @useStatusWithEvent("rangeAttrChange", "focusObjectChange") @@ -12,6 +13,7 @@ class RangeDetails extends Component { public readonly AttrI18nKey: AllI18nKeys[] = [ "Common.Attr.Key.Display.Name", + "Common.Attr.Key.Display", "Common.Attr.Key.Color", "Common.Attr.Key.Position.X", "Common.Attr.Key.Position.Y", @@ -55,40 +57,48 @@ class RangeDetails extends Component { } private renderFrom(range: Range) { - // console.log(range); + + let keyIndex = 0; + return <> - {this.renderAttrInput(range.id, 0, range.displayName, (val, status) => { + {this.renderAttrInput(range.id, keyIndex ++, range.displayName, (val, status) => { status.changeRangeAttrib(range.id, "displayName", val); })} + + { + if (this.props.status) { + this.props.status.changeRangeAttrib(range.id, "display", val); + } + }}/> - { + { if (this.props.status) { this.props.status.changeRangeAttrib(range.id, "color", color); } }}/> - {this.renderAttrInput(range.id, 2, range.position[0], (val, status) => { + {this.renderAttrInput(range.id, keyIndex ++, range.position[0], (val, status) => { range.position[0] = (val as any) / 1; status.changeRangeAttrib(range.id, "position", range.position); }, .1)} - {this.renderAttrInput(range.id, 3, range.position[1], (val, status) => { + {this.renderAttrInput(range.id, keyIndex ++, range.position[1], (val, status) => { range.position[1] = (val as any) / 1; status.changeRangeAttrib(range.id, "position", range.position); }, .1)} - {this.renderAttrInput(range.id, 4, range.position[2], (val, status) => { + {this.renderAttrInput(range.id, keyIndex ++, range.position[2], (val, status) => { range.position[2] = (val as any) / 1; status.changeRangeAttrib(range.id, "position", range.position); }, .1)} - {this.renderAttrInput(range.id, 5, range.radius[0], (val, status) => { + {this.renderAttrInput(range.id, keyIndex ++, range.radius[0], (val, status) => { range.radius[0] = (val as any) / 1; status.changeRangeAttrib(range.id, "radius", range.radius); }, .1, undefined, 0)} - {this.renderAttrInput(range.id, 6, range.radius[1], (val, status) => { + {this.renderAttrInput(range.id, keyIndex ++, range.radius[1], (val, status) => { range.radius[1] = (val as any) / 1; status.changeRangeAttrib(range.id, "radius", range.radius); }, .1, undefined, 0)} - {this.renderAttrInput(range.id, 7, range.radius[2], (val, status) => { + {this.renderAttrInput(range.id, keyIndex ++, range.radius[2], (val, status) => { range.radius[2] = (val as any) / 1; status.changeRangeAttrib(range.id, "radius", range.radius); }, .1, undefined, 0)} -- 2.45.2 From f87da8cbab13d77f6fce74327abe93cef39e4185 Mon Sep 17 00:00:00 2001 From: MrKBear Date: Tue, 8 Mar 2022 20:55:40 +0800 Subject: [PATCH 2/6] Range panel add update attr --- source/Localization/EN-US.ts | 1 + source/Localization/ZH-CN.ts | 1 + source/Panel/RangeDetails/RangeDetails.tsx | 7 +++++++ 3 files changed, 9 insertions(+) diff --git a/source/Localization/EN-US.ts b/source/Localization/EN-US.ts index 752c7a2..513b948 100644 --- a/source/Localization/EN-US.ts +++ b/source/Localization/EN-US.ts @@ -43,6 +43,7 @@ const EN_US = { "Common.Attr.Key.Radius.Z": "Radius Z", "Common.Attr.Key.Color": "Color", "Common.Attr.Key.Display": "Display", + "Common.Attr.Key.Update": "Update", "Common.Attr.Key.Error.Multiple": "Multiple values", "Panel.Info.Range.Details.Attr.Error.Not.Range": "Object is not a Range", "Panel.Info.Range.Details.Attr.Error.Unspecified": "Unspecified range object", diff --git a/source/Localization/ZH-CN.ts b/source/Localization/ZH-CN.ts index dfa4c99..e07c1aa 100644 --- a/source/Localization/ZH-CN.ts +++ b/source/Localization/ZH-CN.ts @@ -43,6 +43,7 @@ const ZH_CN = { "Common.Attr.Key.Radius.Z": "Z 半径", "Common.Attr.Key.Color": "颜色", "Common.Attr.Key.Display": "显示", + "Common.Attr.Key.Update": "更新", "Common.Attr.Key.Error.Multiple": "多重数值", "Panel.Info.Range.Details.Attr.Error.Not.Range": "对象不是一个范围", "Panel.Info.Range.Details.Attr.Error.Unspecified": "未指定范围对象", diff --git a/source/Panel/RangeDetails/RangeDetails.tsx b/source/Panel/RangeDetails/RangeDetails.tsx index 8f0ac55..c28e871 100644 --- a/source/Panel/RangeDetails/RangeDetails.tsx +++ b/source/Panel/RangeDetails/RangeDetails.tsx @@ -14,6 +14,7 @@ class RangeDetails extends Component { public readonly AttrI18nKey: AllI18nKeys[] = [ "Common.Attr.Key.Display.Name", "Common.Attr.Key.Display", + "Common.Attr.Key.Update", "Common.Attr.Key.Color", "Common.Attr.Key.Position.X", "Common.Attr.Key.Position.Y", @@ -71,6 +72,12 @@ class RangeDetails extends Component { } }}/> + { + if (this.props.status) { + this.props.status.changeRangeAttrib(range.id, "update", val); + } + }}/> + { if (this.props.status) { this.props.status.changeRangeAttrib(range.id, "color", color); -- 2.45.2 From 8e3330b398dc4f7b547235ffef7fe6441653daff Mon Sep 17 00:00:00 2001 From: MrKBear Date: Wed, 9 Mar 2022 11:45:00 +0800 Subject: [PATCH 3/6] Add panel error message component --- source/Component/AttrInput/AttrInput.tsx | 9 ++++++++- .../Component/ErrorMessage/ErrorMessage.scss | 3 +++ .../Component/ErrorMessage/ErrorMessage.tsx | 16 ++++++++++++++++ source/Localization/ZH-CN.ts | 2 +- source/Panel/Panel.tsx | 5 ++--- source/Panel/RangeDetails/RangeDetails.tsx | 19 ++++++------------- 6 files changed, 36 insertions(+), 18 deletions(-) create mode 100644 source/Component/ErrorMessage/ErrorMessage.scss create mode 100644 source/Component/ErrorMessage/ErrorMessage.tsx diff --git a/source/Component/AttrInput/AttrInput.tsx b/source/Component/AttrInput/AttrInput.tsx index c496140..03bbc77 100644 --- a/source/Component/AttrInput/AttrInput.tsx +++ b/source/Component/AttrInput/AttrInput.tsx @@ -24,6 +24,13 @@ class AttrInput extends Component { private value: string = ""; private error: ReactNode; + private numberTestReg = [/\.0*$/, /[1-9]+0+$/]; + + private numberTester(value: string) { + return isNaN((value as any) / 1) || + this.numberTestReg[0].test(value) || + this.numberTestReg[1].test(value); + } private check(value: string): ReactNode { @@ -37,7 +44,7 @@ class AttrInput extends Component { const praseNumber = (value as any) / 1; // 数字校验 - if (isNaN(praseNumber) || /\.0*$/.test(value)) { + if (this.numberTester(value)) { return } diff --git a/source/Component/ErrorMessage/ErrorMessage.scss b/source/Component/ErrorMessage/ErrorMessage.scss new file mode 100644 index 0000000..aa33898 --- /dev/null +++ b/source/Component/ErrorMessage/ErrorMessage.scss @@ -0,0 +1,3 @@ +div.panel-error-message { + padding-top: 5px; +} \ No newline at end of file diff --git a/source/Component/ErrorMessage/ErrorMessage.tsx b/source/Component/ErrorMessage/ErrorMessage.tsx new file mode 100644 index 0000000..d82ef9c --- /dev/null +++ b/source/Component/ErrorMessage/ErrorMessage.tsx @@ -0,0 +1,16 @@ +import { AllI18nKeys, Localization } from "@Component/Localization/Localization"; +import { FunctionComponent } from "react"; +import "./ErrorMessage.scss"; + +interface IErrorMessageProps { + i18nKey: AllI18nKeys; + options?: Record; +} + +const ErrorMessage: FunctionComponent = (props) => { + return
+ +
+} + +export { ErrorMessage }; \ No newline at end of file diff --git a/source/Localization/ZH-CN.ts b/source/Localization/ZH-CN.ts index e07c1aa..e0ca849 100644 --- a/source/Localization/ZH-CN.ts +++ b/source/Localization/ZH-CN.ts @@ -26,7 +26,7 @@ const ZH_CN = { "Object.List.New.Group": "组对象 {id}", "Object.List.New.Range": "范围对象 {id}", "Object.List.No.Data": "模型中没有任何对象,点击按钮以创建", - "Panel.Title.Notfound": "找不到面板: {id}", + "Panel.Title.Notfound": "{id}", "Panel.Info.Notfound": "这个编号为 {id} 的面板无法找到!", "Panel.Title.Render.View": "实时预览", "Panel.Info.Render.View": "实时仿真结果预览", diff --git a/source/Panel/Panel.tsx b/source/Panel/Panel.tsx index 66b5c66..a3cddeb 100644 --- a/source/Panel/Panel.tsx +++ b/source/Panel/Panel.tsx @@ -1,6 +1,7 @@ import { ReactNode, Component, FunctionComponent } from "react"; import { Theme } from "@Component/Theme/Theme"; import { Localization } from "@Component/Localization/Localization"; +import { ErrorMessage } from "@Component/ErrorMessage/ErrorMessage"; import { RenderView } from "./RenderView/RenderView"; import { ObjectList } from "./ObjectList/ObjectList"; import { ObjectCommand } from "./ObjectList/ObjectCommand"; @@ -45,9 +46,7 @@ function getPanelById(panelId: PanelId): ReactNode { const C = info.class; return } else return - + } } diff --git a/source/Panel/RangeDetails/RangeDetails.tsx b/source/Panel/RangeDetails/RangeDetails.tsx index c28e871..d8c5362 100644 --- a/source/Panel/RangeDetails/RangeDetails.tsx +++ b/source/Panel/RangeDetails/RangeDetails.tsx @@ -1,7 +1,8 @@ import { Component, ReactNode } from "react"; import { AttrInput } from "@Component/AttrInput/AttrInput"; import { useStatusWithEvent, IMixinStatusProps, Status } from "@Context/Status"; -import { AllI18nKeys } from "@Component/Localization/Localization"; +import { AllI18nKeys, Localization } from "@Component/Localization/Localization"; +import { ErrorMessage } from "@Component/ErrorMessage/ErrorMessage"; import { Range } from "@Model/Range"; import { ObjectID } from "@Model/Renderer"; import { ColorInput } from "@Component/ColorInput/ColorInput"; @@ -24,14 +25,6 @@ class RangeDetails extends Component { "Common.Attr.Key.Radius.Z" ] - private renderErrorFrom(error: AllI18nKeys) { - return <> - {this.AttrI18nKey.map((key, index) => { - return - })} - - } - private renderAttrInput( id: ObjectID, key: number, val: string | number | undefined, change: (val: string, status: Status) => any, @@ -115,10 +108,10 @@ class RangeDetails extends Component { public render(): ReactNode { if (this.props.status) { if (this.props.status.focusObject.size <= 0) { - return this.renderErrorFrom("Panel.Info.Range.Details.Attr.Error.Unspecified"); + return ; } if (this.props.status.focusObject.size > 1) { - return this.renderErrorFrom("Common.Attr.Key.Error.Multiple"); + return ; } let id: ObjectID = 0; this.props.status.focusObject.forEach((cid => id = cid)); @@ -128,10 +121,10 @@ class RangeDetails extends Component { if (range instanceof Range) { return this.renderFrom(range); } else { - return this.renderErrorFrom("Panel.Info.Range.Details.Attr.Error.Not.Range"); + return ; } } - return this.renderErrorFrom("Panel.Info.Range.Details.Attr.Error.Unspecified"); + return ; } } -- 2.45.2 From 97202fe976e3efdca693ee61280959d0821a4e27 Mon Sep 17 00:00:00 2001 From: MrKBear Date: Wed, 9 Mar 2022 11:54:31 +0800 Subject: [PATCH 4/6] Change object id type --- source/Model/Model.ts | 10 +++++----- source/Model/Renderer.ts | 2 +- source/Panel/RangeDetails/RangeDetails.tsx | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/source/Model/Model.ts b/source/Model/Model.ts index cda7ccb..3448165 100644 --- a/source/Model/Model.ts +++ b/source/Model/Model.ts @@ -28,8 +28,8 @@ class Model extends Emitter { * 下一个需要分配的 ID */ private idIndex: number = 1; - public get nextId(): number { - return this.idIndex ++; + public nextId(label: string = "U"): string { + return `${label}-${this.idIndex ++}`; } /** @@ -55,7 +55,7 @@ class Model extends Emitter { */ public addLabel(name: string): Label { console.log(`Model: Creat label with id ${this.idIndex}`); - let label = new Label(this, this.nextId, name); + let label = new Label(this, this.nextId("L"), name); this.labelPool.push(label); this.emit("labelAdd", label); this.emit("labelChange", this.labelPool); @@ -95,7 +95,7 @@ class Model extends Emitter { */ public addGroup(): Group { console.log(`Model: Creat group with id ${this.idIndex}`); - let group = new Group(this, this.nextId); + let group = new Group(this, this.nextId("G")); this.objectPool.push(group); this.emit("groupAdd", group); this.emit("objectAdd", group); @@ -108,7 +108,7 @@ class Model extends Emitter { */ public addRange(): Range { console.log(`Model: Creat range with id ${this.idIndex}`); - let range = new Range(this, this.nextId); + let range = new Range(this, this.nextId("R")); this.objectPool.push(range); this.emit("rangeAdd", range); this.emit("objectAdd", range); diff --git a/source/Model/Renderer.ts b/source/Model/Renderer.ts index d9714f1..2c9ee64 100644 --- a/source/Model/Renderer.ts +++ b/source/Model/Renderer.ts @@ -35,7 +35,7 @@ interface ICommonParam { /** * 对象标识符 */ -type ObjectID = Symbol | string | number; +type ObjectID = string; /** * 接收的数据类型 diff --git a/source/Panel/RangeDetails/RangeDetails.tsx b/source/Panel/RangeDetails/RangeDetails.tsx index d8c5362..101a440 100644 --- a/source/Panel/RangeDetails/RangeDetails.tsx +++ b/source/Panel/RangeDetails/RangeDetails.tsx @@ -113,7 +113,7 @@ class RangeDetails extends Component { if (this.props.status.focusObject.size > 1) { return ; } - let id: ObjectID = 0; + let id: ObjectID = ""; this.props.status.focusObject.forEach((cid => id = cid)); let range = this.props.status!.model.getObjectById(id); -- 2.45.2 From c86a856a3276b6911c48fe50e2698d43ec329d99 Mon Sep 17 00:00:00 2001 From: MrKBear Date: Wed, 9 Mar 2022 14:00:19 +0800 Subject: [PATCH 5/6] Add label list panel --- source/Component/Container/Container.tsx | 14 ++++++------- source/Localization/EN-US.ts | 6 ++++-- source/Localization/ZH-CN.ts | 2 ++ source/Model/Layout.ts | 12 +++++------ source/Page/SimulatorWeb/SimulatorWeb.tsx | 8 +++---- source/Panel/LabelList/LabelList.scss | 18 ++++++++++++++++ source/Panel/LabelList/LabelList.tsx | 16 ++++++++++++++ source/Panel/LabelList/LabelListCommand.tsx | 23 +++++++++++++++++++++ source/Panel/Panel.tsx | 8 ++++++- 9 files changed, 87 insertions(+), 20 deletions(-) create mode 100644 source/Panel/LabelList/LabelList.scss create mode 100644 source/Panel/LabelList/LabelList.tsx create mode 100644 source/Panel/LabelList/LabelListCommand.tsx diff --git a/source/Component/Container/Container.tsx b/source/Component/Container/Container.tsx index 4b8981c..b60e1d5 100644 --- a/source/Component/Container/Container.tsx +++ b/source/Component/Container/Container.tsx @@ -34,11 +34,11 @@ class Container extends Component { /** * 渲染此 Tab 下的 ELE */ - private renderPanel(panles: string[], showBar: boolean, focus?: string) { + private renderPanel(panels: string[], showBar: boolean, focus?: string) { const classList: string[] = []; const theme: Themes = this.props.theme ?? Themes.dark; - const showPanelId = focus ?? panles[0]; + const showPanelId = focus ?? panels[0]; const showPanelInfo = getPanelInfoById(showPanelId as any); classList.push(theme === Themes.light ? "light" : "dark"); @@ -46,14 +46,14 @@ class Container extends Component { classList.push(`font-${FontLevel.Level3}`); classList.push("app-tab-header"); - const hasActivePanel = panles.some((id) => id === this.props.focusId); + const hasActivePanel = panels.some((id) => id === this.props.focusId); return <> {showBar ?
{ this.props.onFocusTab ? this.props.onFocusTab("") : undefined }}>{ - panles.map((panelId: string) => { + panels.map((panelId: string) => { const classList: string[] = ["app-tab-header-item"]; if (panelId === this.props.focusId) classList.push("active"); @@ -189,7 +189,7 @@ class Container extends Component { const items: [IContainerProps, IContainerProps] | undefined = props.items; const showBar: boolean = props.showBar ?? true; - const panles: string[] = props.panles ?? []; + const panels: string[] = props.panels ?? []; const layout: LayoutDirection = props.layout ?? LayoutDirection.Y; const scale: number = props.scale ?? 50; const isRoot: boolean = !!props.isRoot; @@ -201,7 +201,7 @@ class Container extends Component { classList.push(`background-${BackgroundLevel.Level4}`); classList.push(`font-${FontLevel.normal}`); classList.push("app-container"); - if (panles.length > 0 && !items) classList.push("end-containe"); + if (panels.length > 0 && !items) classList.push("end-containe"); return
{ onMouseUp={isRoot ? () => this.focusEdgeId = undefined : undefined} > {/* 渲染 Panel */} - {panles.length > 0 && !items ? this.renderPanel(panles, showBar, focusPanel) : null} + {panels.length > 0 && !items ? this.renderPanel(panels, showBar, focusPanel) : null} {/* 渲染第一部分 */} {items && items[0] ? this.renderContainer(items[0], scale, layout) : null} diff --git a/source/Localization/EN-US.ts b/source/Localization/EN-US.ts index 513b948..a0a0b66 100644 --- a/source/Localization/EN-US.ts +++ b/source/Localization/EN-US.ts @@ -31,9 +31,11 @@ const EN_US = { "Panel.Title.Render.View": "Live preview", "Panel.Info.Render.View": "Live simulation results preview", "Panel.Title.Object.List.View": "Object list", - "Panel.Info.Object.List.View": "Edit View All Object Properties", + "Panel.Info.Object.List.View": "Edit view all Object Properties", "Panel.Title.Range.Details.View": "Range attributes", - "Panel.Info.Range.Details.View": "Edit View Range attributes", + "Panel.Info.Range.Details.View": "Edit view range attributes", + "Panel.Title.Label.List.View": "Label list", + "Panel.Info.Label.List.View": "Edit view label attributes", "Common.Attr.Key.Display.Name": "Display name", "Common.Attr.Key.Position.X": "Position X", "Common.Attr.Key.Position.Y": "Position Y", diff --git a/source/Localization/ZH-CN.ts b/source/Localization/ZH-CN.ts index e0ca849..871f0e6 100644 --- a/source/Localization/ZH-CN.ts +++ b/source/Localization/ZH-CN.ts @@ -34,6 +34,8 @@ const ZH_CN = { "Panel.Info.Object.List.View": "编辑查看全部对象属性", "Panel.Title.Range.Details.View": "范围属性", "Panel.Info.Range.Details.View": "编辑查看范围属性", + "Panel.Title.Label.List.View": "标签列表", + "Panel.Info.Label.List.View": "编辑查看标签属性", "Common.Attr.Key.Display.Name": "显示名称", "Common.Attr.Key.Position.X": "X 坐标", "Common.Attr.Key.Position.Y": "Y 坐标", diff --git a/source/Model/Layout.ts b/source/Model/Layout.ts index 4c14eba..9e5229a 100644 --- a/source/Model/Layout.ts +++ b/source/Model/Layout.ts @@ -7,7 +7,7 @@ enum LayoutDirection { class ILayout { items?: [ILayout, ILayout]; - panles?: string[]; + panels?: string[]; focusPanel?: string; layout?: LayoutDirection; scale?: number; @@ -51,8 +51,8 @@ class Layout extends Emitter { this.id = 0; this.map((layout) => { layout.id = this.id; - if (!layout.focusPanel && layout.panles && layout.panles.length > 0) { - layout.focusPanel = layout.panles[0] + if (!layout.focusPanel && layout.panels && layout.panels.length > 0) { + layout.focusPanel = layout.panels[0] } this.id ++; }); @@ -80,10 +80,10 @@ class Layout extends Emitter { } this.map((layout) => { - if (layout.panles && layout.panles.length > 0) { + if (layout.panels && layout.panels.length > 0) { let index = -1; - for (let i = 0; i < layout.panles.length; i++) { - if (layout.panles[i] === panelId) { + for (let i = 0; i < layout.panels.length; i++) { + if (layout.panels[i] === panelId) { index = i; break; } diff --git a/source/Page/SimulatorWeb/SimulatorWeb.tsx b/source/Page/SimulatorWeb/SimulatorWeb.tsx index ebc510e..dc5c168 100644 --- a/source/Page/SimulatorWeb/SimulatorWeb.tsx +++ b/source/Page/SimulatorWeb/SimulatorWeb.tsx @@ -61,9 +61,9 @@ class SimulatorWeb extends Component { items: [ { items: [ - {panles: ["RenderView", "Label Aa Bb", "Label aaa"]}, + {panels: ["RenderView", "Label Aa Bb", "Label aaa"]}, { - items: [{panles: ["Label b", "Label bbb"]}, {panles: ["C"]}], + items: [{panels: ["Label b", "Label bbb"]}, {panels: ["LabelList"]}], scale: 80, layout: LayoutDirection.X } @@ -73,9 +73,9 @@ class SimulatorWeb extends Component { }, { items: [{ - panles: ["ObjectList", "Test tab"] + panels: ["ObjectList", "Test tab"] }, { - panles: ["RangeDetails", "Label e"] + panels: ["RangeDetails", "Label e"] }], layout: LayoutDirection.Y } diff --git a/source/Panel/LabelList/LabelList.scss b/source/Panel/LabelList/LabelList.scss new file mode 100644 index 0000000..1cee841 --- /dev/null +++ b/source/Panel/LabelList/LabelList.scss @@ -0,0 +1,18 @@ + +div.label-list-command-bar { + width: 100%; + height: 30px; + flex-shrink: 0; + display: flex; + + div.command-item { + width: 30px; + height: 100%; + display: flex; + flex-shrink: 0; + justify-content: center; + align-items: center; + user-select: none; + cursor: pointer; + } +} \ No newline at end of file diff --git a/source/Panel/LabelList/LabelList.tsx b/source/Panel/LabelList/LabelList.tsx new file mode 100644 index 0000000..24a0d48 --- /dev/null +++ b/source/Panel/LabelList/LabelList.tsx @@ -0,0 +1,16 @@ +import { Theme } from "@Component/Theme/Theme"; +import { Component } from "react"; +import "./LabelList.scss"; + +interface ILabelListProps { + +} + +class LabelList extends Component { + + public render() { + return LabelList + } +} + +export { LabelList }; \ No newline at end of file diff --git a/source/Panel/LabelList/LabelListCommand.tsx b/source/Panel/LabelList/LabelListCommand.tsx new file mode 100644 index 0000000..8c7d77b --- /dev/null +++ b/source/Panel/LabelList/LabelListCommand.tsx @@ -0,0 +1,23 @@ +import { BackgroundLevel, FontLevel, Theme } from "@Component/Theme/Theme"; +import { Icon } from "@fluentui/react"; +import { Component } from "react"; +import "./LabelList.scss"; + +interface ILabelListCommandProps {} + +class LabelListCommand extends Component { + + public render() { + return +
+ +
+
+ } +} + +export { LabelListCommand }; \ No newline at end of file diff --git a/source/Panel/Panel.tsx b/source/Panel/Panel.tsx index a3cddeb..6b5cf31 100644 --- a/source/Panel/Panel.tsx +++ b/source/Panel/Panel.tsx @@ -1,11 +1,12 @@ import { ReactNode, Component, FunctionComponent } from "react"; import { Theme } from "@Component/Theme/Theme"; -import { Localization } from "@Component/Localization/Localization"; import { ErrorMessage } from "@Component/ErrorMessage/ErrorMessage"; import { RenderView } from "./RenderView/RenderView"; import { ObjectList } from "./ObjectList/ObjectList"; import { ObjectCommand } from "./ObjectList/ObjectCommand"; import { RangeDetails } from "./RangeDetails/RangeDetails"; +import { LabelList } from "./LabelList/LabelList"; +import { LabelListCommand } from "./LabelList/LabelListCommand"; interface IPanelInfo { nameKey: string; @@ -22,6 +23,7 @@ type PanelId = "" | "RenderView" // 主渲染器 | "ObjectList" // 对象列表 | "RangeDetails" // 范围属性 +| "LabelList" // 标签列表 ; const PanelInfoMap = new Map(); @@ -37,6 +39,10 @@ PanelInfoMap.set("RangeDetails", { nameKey: "Panel.Title.Range.Details.View", introKay: "Panel.Info.Range.Details.View", class: RangeDetails }) +PanelInfoMap.set("LabelList", { + nameKey: "Panel.Title.Label.List.View", introKay: "Panel.Info.Label.List.View", + class: LabelList, header: LabelListCommand, hidePadding: true +}) function getPanelById(panelId: PanelId): ReactNode { switch (panelId) { -- 2.45.2 From 54a03181f140bcc8828e1a85739a77b689977e6d Mon Sep 17 00:00:00 2001 From: MrKBear Date: Wed, 9 Mar 2022 17:23:57 +0800 Subject: [PATCH 6/6] Add label list component --- source/Component/ColorInput/ColorInput.scss | 1 + source/Component/CommandBar/CommandBar.tsx | 8 ++- source/Component/LabelList/LabelList.scss | 64 +++++++++++++++++++++ source/Component/LabelList/LabelList.tsx | 56 ++++++++++++++++++ source/Context/Status.tsx | 22 ++++++- source/Localization/EN-US.ts | 1 + source/Localization/ZH-CN.ts | 1 + source/Model/Label.ts | 8 +-- source/Page/SimulatorWeb/SimulatorWeb.tsx | 2 + source/Panel/LabelList/LabelList.scss | 15 +++++ source/Panel/LabelList/LabelList.tsx | 12 +++- source/Panel/LabelList/LabelListCommand.tsx | 23 -------- source/Panel/Panel.tsx | 3 +- 13 files changed, 182 insertions(+), 34 deletions(-) create mode 100644 source/Component/LabelList/LabelList.scss create mode 100644 source/Component/LabelList/LabelList.tsx delete mode 100644 source/Panel/LabelList/LabelListCommand.tsx diff --git a/source/Component/ColorInput/ColorInput.scss b/source/Component/ColorInput/ColorInput.scss index 8f63de7..4ee5a79 100644 --- a/source/Component/ColorInput/ColorInput.scss +++ b/source/Component/ColorInput/ColorInput.scss @@ -37,6 +37,7 @@ div.color-input-root { div.color-box { width: 12px; height: 12px; + border-radius: 3px; } } diff --git a/source/Component/CommandBar/CommandBar.tsx b/source/Component/CommandBar/CommandBar.tsx index 98e6a14..1b25b6a 100644 --- a/source/Component/CommandBar/CommandBar.tsx +++ b/source/Component/CommandBar/CommandBar.tsx @@ -58,7 +58,13 @@ class CommandBar extends Component { + this.props.status ? this.props.status.newLabel() : undefined; + } + })} {this.getRenderButton({ iconName: "Camera", i18NKey: "Command.Bar.Camera.Info" })}
diff --git a/source/Component/LabelList/LabelList.scss b/source/Component/LabelList/LabelList.scss new file mode 100644 index 0000000..3964103 --- /dev/null +++ b/source/Component/LabelList/LabelList.scss @@ -0,0 +1,64 @@ +@import "../Theme/Theme.scss"; + +div.label { + width: auto; + height: auto; + display: inline-flex; + margin: 5px 5px; + justify-content: center; + vertical-align: middle; + align-items: stretch; + border-radius: 3px; + border: .5px solid transparent; + overflow: hidden; + user-select: none; + cursor: pointer; + + div.label-color { + width: 3px; + margin-right: 2px; + border-radius: 3px; + flex-shrink: 0; + } + + div.label-name { + padding: 2px 3px; + text-overflow: ellipsis; + overflow: hidden; + } + + div.delete-button { + padding: 2px 3px; + border-radius: 3px; + display: flex; + align-items: center; + user-select: none; + cursor: pointer; + } +} + +div.dark.label { + background-color: $lt-bg-color-lvl3-dark; + + div.label-color { + color: $lt-bg-color-lvl3-dark; + } + + div.delete-button:hover { + color: $lt-font-color-lvl2-dark; + background-color: $lt-bg-color-lvl2-dark; + } +} + +div.light.label { + background-color: $lt-bg-color-lvl3-light; + + div.label-color { + color: $lt-bg-color-lvl3-light; + } + + div.delete-button:hover { + color: $lt-font-color-lvl2-light; + background-color: $lt-bg-color-lvl2-light; + } +} \ No newline at end of file diff --git a/source/Component/LabelList/LabelList.tsx b/source/Component/LabelList/LabelList.tsx new file mode 100644 index 0000000..01ca9cf --- /dev/null +++ b/source/Component/LabelList/LabelList.tsx @@ -0,0 +1,56 @@ +import { Component } from "react"; +import { Label } from "@Model/Label"; +import { Icon } from "@fluentui/react"; +import { useSetting, IMixinSettingProps, Themes } from "@Context/Setting"; +import "./LabelList.scss"; + +interface ILabelListProps { + labels: Label[]; + canDelete?: boolean; +} + +interface ILabelListState { + focusLabel?: Label; +} + +@useSetting +class LabelList extends Component { + + public state: Readonly = { + focusLabel: undefined + }; + + private renderLabel(label: Label) { + + const theme = this.props.setting?.themes ?? Themes.dark; + const themeClassName = theme === Themes.dark ? "dark" : "light"; + const colorCss = `rgb(${label.color.join(",")})`; + + return
+
+
+ {label.name} +
+ { + this.props.canDelete ? +
+ +
: null + } +
+ } + + public render() { + return <> + { + this.props.labels.map((label) => { + return this.renderLabel(label); + }) + } + + } +} + +export { LabelList }; \ No newline at end of file diff --git a/source/Context/Status.tsx b/source/Context/Status.tsx index 0c9084f..8573ecd 100644 --- a/source/Context/Status.tsx +++ b/source/Context/Status.tsx @@ -8,12 +8,18 @@ import { ClassicRenderer, MouseMod } from "@GLRender/ClassicRenderer"; import { Setting } from "./Setting"; import { I18N } from "@Component/Localization/Localization"; -function randomColor() { - return [ +function randomColor(unNormal: boolean = false) { + const color = [ Math.random() * .8 + .2, Math.random() * .8 + .2, Math.random() * .8 + .2, 1 ] + if (unNormal) { + color[0] = Math.round(color[0] * 255), + color[1] = Math.round(color[1] * 255), + color[2] = Math.round(color[2] * 255) + } + return color; } interface IStatusEvent { @@ -34,6 +40,7 @@ class Status extends Emitter { * 对象命名 */ public objectNameIndex = 1; + public labelNameIndex = 1; /** * 渲染器 @@ -123,6 +130,17 @@ class Status extends Emitter { return range; } + public newLabel() { + const label = this.model.addLabel( + I18N(this.setting.language, "Object.List.New.Label", { + id: this.labelNameIndex.toString() + }) + ); + label.color = randomColor(true); + this.labelNameIndex ++; + return label; + } + public setMouseMod(mod: MouseMod) { this.mouseMod = mod; if (this.renderer instanceof ClassicRenderer) { diff --git a/source/Localization/EN-US.ts b/source/Localization/EN-US.ts index a0a0b66..39225ae 100644 --- a/source/Localization/EN-US.ts +++ b/source/Localization/EN-US.ts @@ -25,6 +25,7 @@ const EN_US = { "Input.Error.Length": "The length of the input content must be less than {num}", "Object.List.New.Group": "Group object {id}", "Object.List.New.Range": "Range object {id}", + "Object.List.New.Label": "Label {id}", "Object.List.No.Data": "There are no objects in the model, click the button to create it", "Panel.Title.Notfound": "{id}", "Panel.Info.Notfound": "This panel with id {id} can not found!", diff --git a/source/Localization/ZH-CN.ts b/source/Localization/ZH-CN.ts index 871f0e6..1aad911 100644 --- a/source/Localization/ZH-CN.ts +++ b/source/Localization/ZH-CN.ts @@ -25,6 +25,7 @@ const ZH_CN = { "Input.Error.Length": "输入内容长度须小于 {number}", "Object.List.New.Group": "组对象 {id}", "Object.List.New.Range": "范围对象 {id}", + "Object.List.New.Label": "标签 {id}", "Object.List.No.Data": "模型中没有任何对象,点击按钮以创建", "Panel.Title.Notfound": "{id}", "Panel.Info.Notfound": "这个编号为 {id} 的面板无法找到!", diff --git a/source/Model/Label.ts b/source/Model/Label.ts index 13737e1..e9748c8 100644 --- a/source/Model/Label.ts +++ b/source/Model/Label.ts @@ -14,12 +14,12 @@ class Label { /** * 用户定义的名称 */ - public name?: string; + public name: string = ""; /** * CSS 颜色 */ - public color?: string; + public color: number[] = [0, 0, 0]; /** * 所属模型 @@ -31,10 +31,10 @@ class Label { * @param id 标签 ID * @param name 用户定义的名称 */ - public constructor(model:Model, id: ObjectID, name?: string) { + public constructor(model: Model, id: ObjectID, name?: string) { this.model = model; this.id = id; - this.name = name; + this.name = name ?? this.name; } /** diff --git a/source/Page/SimulatorWeb/SimulatorWeb.tsx b/source/Page/SimulatorWeb/SimulatorWeb.tsx index dc5c168..952dcbd 100644 --- a/source/Page/SimulatorWeb/SimulatorWeb.tsx +++ b/source/Page/SimulatorWeb/SimulatorWeb.tsx @@ -51,6 +51,8 @@ class SimulatorWeb extends Component { individual.position[2] = (Math.random() - .5) * 2; }) this.status.model.update(0); + this.status.newLabel().name = "New Label"; + this.status.newLabel().name = "Test Label 01"; } (window as any).s = this; diff --git a/source/Panel/LabelList/LabelList.scss b/source/Panel/LabelList/LabelList.scss index 1cee841..179597e 100644 --- a/source/Panel/LabelList/LabelList.scss +++ b/source/Panel/LabelList/LabelList.scss @@ -1,3 +1,4 @@ +@import "../../Component/Theme/Theme.scss"; div.label-list-command-bar { width: 100%; @@ -15,4 +16,18 @@ div.label-list-command-bar { user-select: none; cursor: pointer; } +} + +div.dark.label-list-command-bar { + + div.command-item:hover { + background-color: $lt-bg-color-lvl3-dark; + } +} + +div.light.label-list-command-bar { + + div.command-item:hover { + background-color: $lt-bg-color-lvl3-light; + } } \ No newline at end of file diff --git a/source/Panel/LabelList/LabelList.tsx b/source/Panel/LabelList/LabelList.tsx index 24a0d48..07908b8 100644 --- a/source/Panel/LabelList/LabelList.tsx +++ b/source/Panel/LabelList/LabelList.tsx @@ -1,15 +1,23 @@ import { Theme } from "@Component/Theme/Theme"; +import { LabelList as LabelListComponent } from "@Component/LabelList/LabelList"; import { Component } from "react"; +import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; +import { Label } from "@Model/Label"; import "./LabelList.scss"; interface ILabelListProps { } -class LabelList extends Component { +@useStatusWithEvent("labelChange") +class LabelList extends Component { public render() { - return LabelList + let labels: Label[] = []; + if (this.props.status) { + labels = this.props.status.model.labelPool.concat([]); + } + return } } diff --git a/source/Panel/LabelList/LabelListCommand.tsx b/source/Panel/LabelList/LabelListCommand.tsx deleted file mode 100644 index 8c7d77b..0000000 --- a/source/Panel/LabelList/LabelListCommand.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { BackgroundLevel, FontLevel, Theme } from "@Component/Theme/Theme"; -import { Icon } from "@fluentui/react"; -import { Component } from "react"; -import "./LabelList.scss"; - -interface ILabelListCommandProps {} - -class LabelListCommand extends Component { - - public render() { - return -
- -
-
- } -} - -export { LabelListCommand }; \ No newline at end of file diff --git a/source/Panel/Panel.tsx b/source/Panel/Panel.tsx index 6b5cf31..747d4cd 100644 --- a/source/Panel/Panel.tsx +++ b/source/Panel/Panel.tsx @@ -6,7 +6,6 @@ import { ObjectList } from "./ObjectList/ObjectList"; import { ObjectCommand } from "./ObjectList/ObjectCommand"; import { RangeDetails } from "./RangeDetails/RangeDetails"; import { LabelList } from "./LabelList/LabelList"; -import { LabelListCommand } from "./LabelList/LabelListCommand"; interface IPanelInfo { nameKey: string; @@ -41,7 +40,7 @@ PanelInfoMap.set("RangeDetails", { }) PanelInfoMap.set("LabelList", { nameKey: "Panel.Title.Label.List.View", introKay: "Panel.Info.Label.List.View", - class: LabelList, header: LabelListCommand, hidePadding: true + class: LabelList }) function getPanelById(panelId: PanelId): ReactNode { -- 2.45.2