From 54a03181f140bcc8828e1a85739a77b689977e6d Mon Sep 17 00:00:00 2001 From: MrKBear Date: Wed, 9 Mar 2022 17:23:57 +0800 Subject: [PATCH] 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 {