Add label list component
This commit is contained in:
parent
c86a856a32
commit
54a03181f1
@ -37,6 +37,7 @@ div.color-input-root {
|
|||||||
div.color-box {
|
div.color-box {
|
||||||
width: 12px;
|
width: 12px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,13 @@ class CommandBar extends Component<ICommandBarProps & IMixinSettingProps & IMixi
|
|||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
{this.getRenderButton({ iconName: "StepSharedAdd", i18NKey: "Command.Bar.Add.Behavior.Info" })}
|
{this.getRenderButton({ iconName: "StepSharedAdd", i18NKey: "Command.Bar.Add.Behavior.Info" })}
|
||||||
{this.getRenderButton({ iconName: "Tag", i18NKey: "Command.Bar.Add.Tag.Info" })}
|
{this.getRenderButton({
|
||||||
|
iconName: "Tag",
|
||||||
|
i18NKey: "Command.Bar.Add.Tag.Info",
|
||||||
|
click: () => {
|
||||||
|
this.props.status ? this.props.status.newLabel() : undefined;
|
||||||
|
}
|
||||||
|
})}
|
||||||
{this.getRenderButton({ iconName: "Camera", i18NKey: "Command.Bar.Camera.Info" })}
|
{this.getRenderButton({ iconName: "Camera", i18NKey: "Command.Bar.Camera.Info" })}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
64
source/Component/LabelList/LabelList.scss
Normal file
64
source/Component/LabelList/LabelList.scss
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
56
source/Component/LabelList/LabelList.tsx
Normal file
56
source/Component/LabelList/LabelList.tsx
Normal file
@ -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<ILabelListProps & IMixinSettingProps, ILabelListState> {
|
||||||
|
|
||||||
|
public state: Readonly<ILabelListState> = {
|
||||||
|
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 <div className={`label ${themeClassName}`} key={label.id}>
|
||||||
|
<div className="label-color" style={{
|
||||||
|
backgroundColor: colorCss
|
||||||
|
}}/>
|
||||||
|
<div className="label-name">
|
||||||
|
{label.name}
|
||||||
|
</div>
|
||||||
|
{
|
||||||
|
this.props.canDelete ?
|
||||||
|
<div className="delete-button">
|
||||||
|
<Icon iconName="delete"></Icon>
|
||||||
|
</div> : null
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
return <>
|
||||||
|
{
|
||||||
|
this.props.labels.map((label) => {
|
||||||
|
return this.renderLabel(label);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { LabelList };
|
@ -8,12 +8,18 @@ import { ClassicRenderer, MouseMod } from "@GLRender/ClassicRenderer";
|
|||||||
import { Setting } from "./Setting";
|
import { Setting } from "./Setting";
|
||||||
import { I18N } from "@Component/Localization/Localization";
|
import { I18N } from "@Component/Localization/Localization";
|
||||||
|
|
||||||
function randomColor() {
|
function randomColor(unNormal: boolean = false) {
|
||||||
return [
|
const color = [
|
||||||
Math.random() * .8 + .2,
|
Math.random() * .8 + .2,
|
||||||
Math.random() * .8 + .2,
|
Math.random() * .8 + .2,
|
||||||
Math.random() * .8 + .2, 1
|
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 {
|
interface IStatusEvent {
|
||||||
@ -34,6 +40,7 @@ class Status extends Emitter<IStatusEvent> {
|
|||||||
* 对象命名
|
* 对象命名
|
||||||
*/
|
*/
|
||||||
public objectNameIndex = 1;
|
public objectNameIndex = 1;
|
||||||
|
public labelNameIndex = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 渲染器
|
* 渲染器
|
||||||
@ -123,6 +130,17 @@ class Status extends Emitter<IStatusEvent> {
|
|||||||
return range;
|
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) {
|
public setMouseMod(mod: MouseMod) {
|
||||||
this.mouseMod = mod;
|
this.mouseMod = mod;
|
||||||
if (this.renderer instanceof ClassicRenderer) {
|
if (this.renderer instanceof ClassicRenderer) {
|
||||||
|
@ -25,6 +25,7 @@ const EN_US = {
|
|||||||
"Input.Error.Length": "The length of the input content must be less than {num}",
|
"Input.Error.Length": "The length of the input content must be less than {num}",
|
||||||
"Object.List.New.Group": "Group object {id}",
|
"Object.List.New.Group": "Group object {id}",
|
||||||
"Object.List.New.Range": "Range 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",
|
"Object.List.No.Data": "There are no objects in the model, click the button to create it",
|
||||||
"Panel.Title.Notfound": "{id}",
|
"Panel.Title.Notfound": "{id}",
|
||||||
"Panel.Info.Notfound": "This panel with id {id} can not found!",
|
"Panel.Info.Notfound": "This panel with id {id} can not found!",
|
||||||
|
@ -25,6 +25,7 @@ const ZH_CN = {
|
|||||||
"Input.Error.Length": "输入内容长度须小于 {number}",
|
"Input.Error.Length": "输入内容长度须小于 {number}",
|
||||||
"Object.List.New.Group": "组对象 {id}",
|
"Object.List.New.Group": "组对象 {id}",
|
||||||
"Object.List.New.Range": "范围对象 {id}",
|
"Object.List.New.Range": "范围对象 {id}",
|
||||||
|
"Object.List.New.Label": "标签 {id}",
|
||||||
"Object.List.No.Data": "模型中没有任何对象,点击按钮以创建",
|
"Object.List.No.Data": "模型中没有任何对象,点击按钮以创建",
|
||||||
"Panel.Title.Notfound": "{id}",
|
"Panel.Title.Notfound": "{id}",
|
||||||
"Panel.Info.Notfound": "这个编号为 {id} 的面板无法找到!",
|
"Panel.Info.Notfound": "这个编号为 {id} 的面板无法找到!",
|
||||||
|
@ -14,12 +14,12 @@ class Label {
|
|||||||
/**
|
/**
|
||||||
* 用户定义的名称
|
* 用户定义的名称
|
||||||
*/
|
*/
|
||||||
public name?: string;
|
public name: string = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CSS 颜色
|
* CSS 颜色
|
||||||
*/
|
*/
|
||||||
public color?: string;
|
public color: number[] = [0, 0, 0];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 所属模型
|
* 所属模型
|
||||||
@ -34,7 +34,7 @@ class Label {
|
|||||||
public constructor(model: Model, id: ObjectID, name?: string) {
|
public constructor(model: Model, id: ObjectID, name?: string) {
|
||||||
this.model = model;
|
this.model = model;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name ?? this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,6 +51,8 @@ class SimulatorWeb extends Component {
|
|||||||
individual.position[2] = (Math.random() - .5) * 2;
|
individual.position[2] = (Math.random() - .5) * 2;
|
||||||
})
|
})
|
||||||
this.status.model.update(0);
|
this.status.model.update(0);
|
||||||
|
this.status.newLabel().name = "New Label";
|
||||||
|
this.status.newLabel().name = "Test Label 01";
|
||||||
}
|
}
|
||||||
|
|
||||||
(window as any).s = this;
|
(window as any).s = this;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
@import "../../Component/Theme/Theme.scss";
|
||||||
|
|
||||||
div.label-list-command-bar {
|
div.label-list-command-bar {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -16,3 +17,17 @@ div.label-list-command-bar {
|
|||||||
cursor: pointer;
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,23 @@
|
|||||||
import { Theme } from "@Component/Theme/Theme";
|
import { Theme } from "@Component/Theme/Theme";
|
||||||
|
import { LabelList as LabelListComponent } from "@Component/LabelList/LabelList";
|
||||||
import { Component } from "react";
|
import { Component } from "react";
|
||||||
|
import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status";
|
||||||
|
import { Label } from "@Model/Label";
|
||||||
import "./LabelList.scss";
|
import "./LabelList.scss";
|
||||||
|
|
||||||
interface ILabelListProps {
|
interface ILabelListProps {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class LabelList extends Component<ILabelListProps> {
|
@useStatusWithEvent("labelChange")
|
||||||
|
class LabelList extends Component<ILabelListProps & IMixinStatusProps> {
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
return <Theme>LabelList</Theme>
|
let labels: Label[] = [];
|
||||||
|
if (this.props.status) {
|
||||||
|
labels = this.props.status.model.labelPool.concat([]);
|
||||||
|
}
|
||||||
|
return <LabelListComponent labels={labels} canDelete/>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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<ILabelListCommandProps> {
|
|
||||||
|
|
||||||
public render() {
|
|
||||||
return <Theme
|
|
||||||
className="label-list-command-bar"
|
|
||||||
backgroundLevel={BackgroundLevel.Level4}
|
|
||||||
fontLevel={FontLevel.normal}
|
|
||||||
>
|
|
||||||
<div className="command-item">
|
|
||||||
<Icon iconName="Tag"></Icon>
|
|
||||||
</div>
|
|
||||||
</Theme>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { LabelListCommand };
|
|
@ -6,7 +6,6 @@ import { ObjectList } from "./ObjectList/ObjectList";
|
|||||||
import { ObjectCommand } from "./ObjectList/ObjectCommand";
|
import { ObjectCommand } from "./ObjectList/ObjectCommand";
|
||||||
import { RangeDetails } from "./RangeDetails/RangeDetails";
|
import { RangeDetails } from "./RangeDetails/RangeDetails";
|
||||||
import { LabelList } from "./LabelList/LabelList";
|
import { LabelList } from "./LabelList/LabelList";
|
||||||
import { LabelListCommand } from "./LabelList/LabelListCommand";
|
|
||||||
|
|
||||||
interface IPanelInfo {
|
interface IPanelInfo {
|
||||||
nameKey: string;
|
nameKey: string;
|
||||||
@ -41,7 +40,7 @@ PanelInfoMap.set("RangeDetails", {
|
|||||||
})
|
})
|
||||||
PanelInfoMap.set("LabelList", {
|
PanelInfoMap.set("LabelList", {
|
||||||
nameKey: "Panel.Title.Label.List.View", introKay: "Panel.Info.Label.List.View",
|
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 {
|
function getPanelById(panelId: PanelId): ReactNode {
|
||||||
|
Loading…
Reference in New Issue
Block a user