Compare commits
	
		
			No commits in common. "edb24b27fb024572f57551092944f895389a17a8" and "f0a04875e455d69b649ef89cbf7b51ead32a3886" have entirely different histories.
		
	
	
		
			edb24b27fb
			...
			f0a04875e4
		
	
		
| @ -24,13 +24,6 @@ class AttrInput extends Component<IAttrInputProps> { | ||||
| 
 | ||||
|     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 { | ||||
| 
 | ||||
| @ -44,7 +37,7 @@ class AttrInput extends Component<IAttrInputProps> { | ||||
|             const praseNumber = (value as any) / 1; | ||||
| 
 | ||||
|             // 数字校验
 | ||||
|             if (this.numberTester(value)) { | ||||
|             if (isNaN(praseNumber) || /\.0*$/.test(value)) { | ||||
|                 return <Localization i18nKey="Input.Error.Not.Number" /> | ||||
|             } | ||||
| 
 | ||||
|  | ||||
| @ -37,7 +37,6 @@ div.color-input-root { | ||||
|             div.color-box { | ||||
|                 width: 12px; | ||||
|                 height: 12px; | ||||
|                 border-radius: 3px; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -58,13 +58,7 @@ class CommandBar extends Component<ICommandBarProps & IMixinSettingProps & IMixi | ||||
|                     } | ||||
|                 })} | ||||
|                 {this.getRenderButton({ iconName: "StepSharedAdd", i18NKey: "Command.Bar.Add.Behavior.Info" })} | ||||
|                 {this.getRenderButton({ | ||||
|                     iconName: "Tag", | ||||
|                     i18NKey: "Command.Bar.Add.Tag.Info", | ||||
|                     click: () => { | ||||
|                         this.props.status ? this.props.status.newLabel() : undefined; | ||||
|                     } | ||||
|                 })} | ||||
|                 {this.getRenderButton({ iconName: "Tag", i18NKey: "Command.Bar.Add.Tag.Info" })} | ||||
|                 {this.getRenderButton({ iconName: "Camera", i18NKey: "Command.Bar.Camera.Info" })} | ||||
|             </div> | ||||
|             <div> | ||||
|  | ||||
| @ -34,11 +34,11 @@ class Container extends Component<IContainerProps> { | ||||
| 	/** | ||||
| 	 * 渲染此 Tab 下的 ELE | ||||
| 	 */ | ||||
| 	private renderPanel(panels: string[], showBar: boolean, focus?: string) { | ||||
| 	private renderPanel(panles: string[], showBar: boolean, focus?: string) { | ||||
| 
 | ||||
| 		const classList: string[] = []; | ||||
| 		const theme: Themes = this.props.theme ?? Themes.dark; | ||||
| 		const showPanelId = focus ?? panels[0]; | ||||
| 		const showPanelId = focus ?? panles[0]; | ||||
| 		const showPanelInfo = getPanelInfoById(showPanelId as any); | ||||
| 
 | ||||
| 		classList.push(theme === Themes.light ? "light" : "dark"); | ||||
| @ -46,14 +46,14 @@ class Container extends Component<IContainerProps> { | ||||
| 		classList.push(`font-${FontLevel.Level3}`); | ||||
| 		classList.push("app-tab-header"); | ||||
| 
 | ||||
| 		const hasActivePanel = panels.some((id) => id === this.props.focusId); | ||||
| 		const hasActivePanel = panles.some((id) => id === this.props.focusId); | ||||
| 
 | ||||
| 		return <> | ||||
| 			{showBar ?  | ||||
| 				<div className={classList.join(" ")} onClick={() => { | ||||
| 					this.props.onFocusTab ? this.props.onFocusTab("") : undefined | ||||
| 				}}>{ | ||||
| 					panels.map((panelId: string) => { | ||||
| 					panles.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<IContainerProps> { | ||||
| 
 | ||||
| 		const items: [IContainerProps, IContainerProps] | undefined = props.items; | ||||
| 		const showBar: boolean = props.showBar ?? true; | ||||
| 		const panels: string[] = props.panels ?? []; | ||||
| 		const panles: string[] = props.panles ?? []; | ||||
| 		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<IContainerProps> { | ||||
| 		classList.push(`background-${BackgroundLevel.Level4}`); | ||||
| 		classList.push(`font-${FontLevel.normal}`); | ||||
| 		classList.push("app-container"); | ||||
| 		if (panels.length > 0 && !items) classList.push("end-containe"); | ||||
| 		if (panles.length > 0 && !items) classList.push("end-containe"); | ||||
| 
 | ||||
| 		return <div | ||||
| 			className={classList.join(" ")} | ||||
| @ -216,7 +216,7 @@ class Container extends Component<IContainerProps> { | ||||
| 			onMouseUp={isRoot ? () => this.focusEdgeId = undefined : undefined} | ||||
| 		> | ||||
| 			{/* 渲染 Panel */} | ||||
| 			{panels.length > 0 && !items ? this.renderPanel(panels, showBar, focusPanel) : null} | ||||
| 			{panles.length > 0 && !items ? this.renderPanel(panles, showBar, focusPanel) : null} | ||||
| 
 | ||||
| 			{/* 渲染第一部分 */} | ||||
| 			{items && items[0] ? this.renderContainer(items[0], scale, layout) : null} | ||||
|  | ||||
| @ -1,3 +0,0 @@ | ||||
| div.panel-error-message { | ||||
|     padding-top: 5px; | ||||
| } | ||||
| @ -1,16 +0,0 @@ | ||||
| import { AllI18nKeys, Localization } from "@Component/Localization/Localization"; | ||||
| import { FunctionComponent } from "react"; | ||||
| import "./ErrorMessage.scss"; | ||||
| 
 | ||||
| interface IErrorMessageProps { | ||||
|     i18nKey: AllI18nKeys; | ||||
|     options?: Record<string, string>; | ||||
| } | ||||
| 
 | ||||
| const ErrorMessage: FunctionComponent<IErrorMessageProps> = (props) => { | ||||
|     return <div className="panel-error-message"> | ||||
|         <Localization i18nKey={props.i18nKey} options={props.options}/> | ||||
|     </div> | ||||
| } | ||||
| 
 | ||||
| export { ErrorMessage }; | ||||
| @ -1,64 +0,0 @@ | ||||
| @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; | ||||
|     } | ||||
| } | ||||
| @ -1,56 +0,0 @@ | ||||
| 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 }; | ||||
| @ -1,63 +0,0 @@ | ||||
| @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; | ||||
| 	} | ||||
| } | ||||
| @ -1,45 +0,0 @@ | ||||
| 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<ITogglesInputProps> { | ||||
|     public render(): ReactNode { | ||||
|         return <Theme className="toggles-input"> | ||||
|             <div className="toggles-intro"> | ||||
|                 <Localization i18nKey={this.props.keyI18n}/> | ||||
|             </div> | ||||
|             <div className="toggles-content"> | ||||
|                 <div | ||||
|                     className="checkbox" | ||||
|                     style={{ | ||||
|                         cursor: this.props.disable ? "not-allowed" : "pointer" | ||||
|                     }} | ||||
|                     onClick={(() => { | ||||
|                         if (this.props.disable) { | ||||
|                             return; | ||||
|                         } | ||||
|                         if (this.props.valueChange) { | ||||
|                             this.props.valueChange(!this.props.value); | ||||
|                         } | ||||
|                     })} | ||||
|                 > | ||||
|                     <Icon iconName="CheckMark" style={{ | ||||
|                         display: this.props.value ? "inline-block" : "none" | ||||
|                     }}></Icon> | ||||
|                 </div>     | ||||
|             </div> | ||||
|         </Theme> | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export { TogglesInput }; | ||||
| @ -8,18 +8,12 @@ import { ClassicRenderer, MouseMod } from "@GLRender/ClassicRenderer"; | ||||
| import { Setting } from "./Setting"; | ||||
| import { I18N } from "@Component/Localization/Localization"; | ||||
| 
 | ||||
| function randomColor(unNormal: boolean = false) { | ||||
|     const color = [ | ||||
| function randomColor() { | ||||
|     return [ | ||||
|         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 { | ||||
| @ -40,7 +34,6 @@ class Status extends Emitter<IStatusEvent> { | ||||
|      * 对象命名 | ||||
|      */ | ||||
|     public objectNameIndex = 1; | ||||
|     public labelNameIndex = 1; | ||||
| 
 | ||||
|     /** | ||||
|      * 渲染器 | ||||
| @ -130,17 +123,6 @@ class Status extends Emitter<IStatusEvent> { | ||||
|         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) { | ||||
|  | ||||
| @ -25,18 +25,15 @@ 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!", | ||||
|     "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.Title.Label.List.View": "Label list", | ||||
|     "Panel.Info.Label.List.View": "Edit view label attributes", | ||||
|     "Panel.Info.Range.Details.View": "Edit View Range attributes", | ||||
|     "Common.Attr.Key.Display.Name": "Display name", | ||||
|     "Common.Attr.Key.Position.X": "Position X", | ||||
|     "Common.Attr.Key.Position.Y": "Position Y", | ||||
| @ -45,8 +42,6 @@ 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.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", | ||||
|  | ||||
| @ -25,9 +25,8 @@ 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.Title.Notfound": "找不到面板: {id}", | ||||
|     "Panel.Info.Notfound": "这个编号为 {id} 的面板无法找到!", | ||||
|     "Panel.Title.Render.View": "实时预览", | ||||
|     "Panel.Info.Render.View": "实时仿真结果预览", | ||||
| @ -35,8 +34,6 @@ 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 坐标", | ||||
| @ -45,8 +42,6 @@ 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.Update": "更新", | ||||
|     "Common.Attr.Key.Error.Multiple": "多重数值", | ||||
|     "Panel.Info.Range.Details.Attr.Error.Not.Range": "对象不是一个范围", | ||||
|     "Panel.Info.Range.Details.Attr.Error.Unspecified": "未指定范围对象", | ||||
|  | ||||
| @ -14,12 +14,12 @@ class Label { | ||||
|     /** | ||||
|      * 用户定义的名称 | ||||
|      */ | ||||
|     public name: string = ""; | ||||
|     public name?: string; | ||||
| 
 | ||||
|     /** | ||||
|      * CSS 颜色 | ||||
|      */ | ||||
|     public color: number[] = [0, 0, 0]; | ||||
|     public color?: string; | ||||
| 
 | ||||
|     /** | ||||
|      * 所属模型 | ||||
| @ -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; | ||||
|         this.name = name; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -7,7 +7,7 @@ enum LayoutDirection { | ||||
| 
 | ||||
| class ILayout { | ||||
| 	items?: [ILayout, ILayout]; | ||||
| 	panels?: string[]; | ||||
| 	panles?: string[]; | ||||
| 	focusPanel?: string; | ||||
| 	layout?: LayoutDirection; | ||||
| 	scale?: number; | ||||
| @ -51,8 +51,8 @@ class Layout extends Emitter<ILayoutEvent> { | ||||
| 		this.id = 0; | ||||
| 		this.map((layout) => { | ||||
| 			layout.id = this.id; | ||||
| 			if (!layout.focusPanel && layout.panels && layout.panels.length > 0) { | ||||
| 				layout.focusPanel = layout.panels[0] | ||||
| 			if (!layout.focusPanel && layout.panles && layout.panles.length > 0) { | ||||
| 				layout.focusPanel = layout.panles[0] | ||||
| 			} | ||||
| 			this.id ++; | ||||
| 		}); | ||||
| @ -80,10 +80,10 @@ class Layout extends Emitter<ILayoutEvent> { | ||||
| 		} | ||||
| 
 | ||||
| 		this.map((layout) => { | ||||
| 			if (layout.panels && layout.panels.length > 0) { | ||||
| 			if (layout.panles && layout.panles.length > 0) { | ||||
| 				let index = -1; | ||||
| 				for (let i = 0; i < layout.panels.length; i++) { | ||||
| 					if (layout.panels[i] === panelId) { | ||||
| 				for (let i = 0; i < layout.panles.length; i++) { | ||||
| 					if (layout.panles[i] === panelId) { | ||||
| 						index = i; | ||||
| 						break; | ||||
| 					} | ||||
|  | ||||
| @ -28,8 +28,8 @@ class Model extends Emitter<ModelEvent> { | ||||
|      * 下一个需要分配的 ID | ||||
|      */ | ||||
|     private idIndex: number = 1; | ||||
|     public nextId(label: string = "U"): string { | ||||
|         return `${label}-${this.idIndex ++}`; | ||||
|     public get nextId(): number { | ||||
|         return this.idIndex ++; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -55,7 +55,7 @@ class Model extends Emitter<ModelEvent> { | ||||
|      */ | ||||
|     public addLabel(name: string): Label { | ||||
|         console.log(`Model: Creat label with id ${this.idIndex}`); | ||||
|         let label = new Label(this, this.nextId("L"), name); | ||||
|         let label = new Label(this, this.nextId, name); | ||||
|         this.labelPool.push(label); | ||||
|         this.emit("labelAdd", label); | ||||
|         this.emit("labelChange", this.labelPool); | ||||
| @ -95,7 +95,7 @@ class Model extends Emitter<ModelEvent> { | ||||
|      */ | ||||
|     public addGroup(): Group { | ||||
|         console.log(`Model: Creat group with id ${this.idIndex}`); | ||||
|         let group = new Group(this, this.nextId("G")); | ||||
|         let group = new Group(this, this.nextId); | ||||
|         this.objectPool.push(group); | ||||
|         this.emit("groupAdd", group); | ||||
|         this.emit("objectAdd", group); | ||||
| @ -108,7 +108,7 @@ class Model extends Emitter<ModelEvent> { | ||||
|      */ | ||||
|     public addRange(): Range { | ||||
|         console.log(`Model: Creat range with id ${this.idIndex}`); | ||||
|         let range = new Range(this, this.nextId("R")); | ||||
|         let range = new Range(this, this.nextId); | ||||
|         this.objectPool.push(range); | ||||
|         this.emit("rangeAdd", range); | ||||
|         this.emit("objectAdd", range); | ||||
|  | ||||
| @ -35,7 +35,7 @@ interface ICommonParam { | ||||
| /** | ||||
|  * 对象标识符 | ||||
|  */ | ||||
| type ObjectID = string; | ||||
| type ObjectID = Symbol | string | number; | ||||
| 
 | ||||
| /** | ||||
|  * 接收的数据类型 | ||||
|  | ||||
| @ -51,8 +51,6 @@ 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; | ||||
| @ -63,9 +61,9 @@ class SimulatorWeb extends Component { | ||||
|             items: [ | ||||
|                 { | ||||
|                     items: [ | ||||
|                         {panels: ["RenderView", "Label Aa Bb", "Label aaa"]}, | ||||
|                         {panles: ["RenderView", "Label Aa Bb", "Label aaa"]}, | ||||
|                         { | ||||
|                             items: [{panels: ["Label b", "Label bbb"]}, {panels: ["LabelList"]}], | ||||
|                             items: [{panles: ["Label b", "Label bbb"]}, {panles: ["C"]}], | ||||
|                             scale: 80, | ||||
|                             layout: LayoutDirection.X | ||||
|                         } | ||||
| @ -75,9 +73,9 @@ class SimulatorWeb extends Component { | ||||
|                 }, | ||||
|                 { | ||||
|                     items: [{ | ||||
|                         panels: ["ObjectList", "Test tab"] | ||||
|                         panles: ["ObjectList", "Test tab"] | ||||
|                     }, { | ||||
|                         panels: ["RangeDetails", "Label e"] | ||||
|                         panles: ["RangeDetails", "Label e"] | ||||
|                     }], | ||||
|                     layout: LayoutDirection.Y | ||||
|                 } | ||||
|  | ||||
| @ -1,33 +0,0 @@ | ||||
| @import "../../Component/Theme/Theme.scss"; | ||||
| 
 | ||||
| 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; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 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,24 +0,0 @@ | ||||
| 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 { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| @useStatusWithEvent("labelChange") | ||||
| class LabelList extends Component<ILabelListProps & IMixinStatusProps> { | ||||
|      | ||||
|     public render() { | ||||
|         let labels: Label[] = []; | ||||
|         if (this.props.status) { | ||||
|             labels = this.props.status.model.labelPool.concat([]); | ||||
|         } | ||||
|         return <LabelListComponent labels={labels} canDelete/> | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export { LabelList }; | ||||
| @ -1,11 +1,10 @@ | ||||
| import { ReactNode, Component, FunctionComponent } from "react"; | ||||
| import { Theme } from "@Component/Theme/Theme"; | ||||
| import { ErrorMessage } from "@Component/ErrorMessage/ErrorMessage"; | ||||
| import { Localization } from "@Component/Localization/Localization"; | ||||
| 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"; | ||||
| 
 | ||||
| interface IPanelInfo { | ||||
| 	nameKey: string; | ||||
| @ -22,7 +21,6 @@ type PanelId = "" | ||||
| | "RenderView" // 主渲染器
 | ||||
| | "ObjectList" // 对象列表
 | ||||
| | "RangeDetails" // 范围属性
 | ||||
| | "LabelList" // 标签列表
 | ||||
| ; | ||||
| 
 | ||||
| const PanelInfoMap = new Map<PanelId, IPanelInfo>(); | ||||
| @ -38,10 +36,6 @@ 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 | ||||
| }) | ||||
| 
 | ||||
| function getPanelById(panelId: PanelId): ReactNode { | ||||
| 	switch (panelId) { | ||||
| @ -51,7 +45,9 @@ function getPanelById(panelId: PanelId): ReactNode { | ||||
| 				const C = info.class; | ||||
| 				return <C></C> | ||||
| 			} else return <Theme> | ||||
| 				<ErrorMessage i18nKey={"Panel.Info.Notfound"} options={{ id: panelId }}/> | ||||
| 				<Localization i18nKey={"Panel.Info.Notfound"} options={{ | ||||
| 					id: panelId | ||||
| 				}}/> | ||||
| 			</Theme> | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -1,12 +1,10 @@ | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { AttrInput } from "@Component/AttrInput/AttrInput"; | ||||
| import { useStatusWithEvent, IMixinStatusProps, Status } from "@Context/Status"; | ||||
| import { AllI18nKeys, Localization } from "@Component/Localization/Localization"; | ||||
| import { ErrorMessage } from "@Component/ErrorMessage/ErrorMessage"; | ||||
| 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") | ||||
| @ -14,8 +12,6 @@ class RangeDetails extends Component<IMixinStatusProps> { | ||||
|      | ||||
|     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", | ||||
| @ -25,6 +21,14 @@ class RangeDetails extends Component<IMixinStatusProps> { | ||||
|         "Common.Attr.Key.Radius.Z" | ||||
|     ] | ||||
| 
 | ||||
|     private renderErrorFrom(error: AllI18nKeys) { | ||||
|         return <> | ||||
|             {this.AttrI18nKey.map((key, index) => { | ||||
|                 return <AttrInput key={index} keyI18n={key} disable disableI18n={error}/> | ||||
|             })} | ||||
|         </> | ||||
|     } | ||||
| 
 | ||||
|     private renderAttrInput( | ||||
|         id: ObjectID, key: number, val: string | number | undefined, | ||||
|         change: (val: string, status: Status) => any, | ||||
| @ -51,54 +55,40 @@ class RangeDetails extends Component<IMixinStatusProps> { | ||||
|     } | ||||
| 
 | ||||
|     private renderFrom(range: Range) { | ||||
|          | ||||
|         let keyIndex = 0; | ||||
| 
 | ||||
|         // console.log(range);
 | ||||
|         return <> | ||||
|             {this.renderAttrInput(range.id, keyIndex ++, range.displayName, (val, status) => { | ||||
|             {this.renderAttrInput(range.id, 0, range.displayName, (val, status) => { | ||||
|                 status.changeRangeAttrib(range.id, "displayName", val); | ||||
|             })} | ||||
|              | ||||
|             <TogglesInput keyI18n={this.AttrI18nKey[keyIndex ++]} value={range.display} valueChange={(val) => { | ||||
|                 if (this.props.status) { | ||||
|                     this.props.status.changeRangeAttrib(range.id, "display", val); | ||||
|                 } | ||||
|             }}/> | ||||
| 
 | ||||
|             <TogglesInput keyI18n={this.AttrI18nKey[keyIndex ++]} value={range.update} valueChange={(val) => { | ||||
|                 if (this.props.status) { | ||||
|                     this.props.status.changeRangeAttrib(range.id, "update", val); | ||||
|                 } | ||||
|             }}/> | ||||
| 
 | ||||
|             <ColorInput keyI18n={this.AttrI18nKey[keyIndex ++]} value={range.color} normal valueChange={(color) => { | ||||
|             <ColorInput keyI18n="Common.Attr.Key.Color" value={range.color} normal valueChange={(color) => { | ||||
|                 if (this.props.status) { | ||||
|                     this.props.status.changeRangeAttrib(range.id, "color", color); | ||||
|                 } | ||||
|             }}/> | ||||
| 
 | ||||
|             {this.renderAttrInput(range.id, keyIndex ++, range.position[0], (val, status) => { | ||||
|             {this.renderAttrInput(range.id, 2, range.position[0], (val, status) => { | ||||
|                 range.position[0] = (val as any) / 1; | ||||
|                 status.changeRangeAttrib(range.id, "position", range.position); | ||||
|             }, .1)} | ||||
|             {this.renderAttrInput(range.id, keyIndex ++, range.position[1], (val, status) => { | ||||
|             {this.renderAttrInput(range.id, 3, range.position[1], (val, status) => { | ||||
|                 range.position[1] = (val as any) / 1; | ||||
|                 status.changeRangeAttrib(range.id, "position", range.position); | ||||
|             }, .1)} | ||||
|             {this.renderAttrInput(range.id, keyIndex ++, range.position[2], (val, status) => { | ||||
|             {this.renderAttrInput(range.id, 4, range.position[2], (val, status) => { | ||||
|                 range.position[2] = (val as any) / 1; | ||||
|                 status.changeRangeAttrib(range.id, "position", range.position); | ||||
|             }, .1)} | ||||
| 			 | ||||
|             {this.renderAttrInput(range.id, keyIndex ++, range.radius[0], (val, status) => { | ||||
|             {this.renderAttrInput(range.id, 5, 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, keyIndex ++, range.radius[1], (val, status) => { | ||||
|             {this.renderAttrInput(range.id, 6, 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, keyIndex ++, range.radius[2], (val, status) => { | ||||
|             {this.renderAttrInput(range.id, 7, range.radius[2], (val, status) => { | ||||
|                 range.radius[2] = (val as any) / 1; | ||||
|                 status.changeRangeAttrib(range.id, "radius", range.radius); | ||||
|             }, .1, undefined, 0)} | ||||
| @ -108,12 +98,12 @@ class RangeDetails extends Component<IMixinStatusProps> { | ||||
| 	public render(): ReactNode { | ||||
|         if (this.props.status) { | ||||
|             if (this.props.status.focusObject.size <= 0) { | ||||
|                 return <ErrorMessage i18nKey="Panel.Info.Range.Details.Attr.Error.Unspecified"/>; | ||||
|                 return this.renderErrorFrom("Panel.Info.Range.Details.Attr.Error.Unspecified"); | ||||
|             } | ||||
|             if (this.props.status.focusObject.size > 1) { | ||||
|                 return <ErrorMessage i18nKey="Common.Attr.Key.Error.Multiple"/>; | ||||
|                 return this.renderErrorFrom("Common.Attr.Key.Error.Multiple"); | ||||
|             } | ||||
|             let id: ObjectID = ""; | ||||
|             let id: ObjectID = 0; | ||||
|             this.props.status.focusObject.forEach((cid => id = cid)); | ||||
|              | ||||
|             let range = this.props.status!.model.getObjectById(id); | ||||
| @ -121,10 +111,10 @@ class RangeDetails extends Component<IMixinStatusProps> { | ||||
|             if (range instanceof Range) { | ||||
|                 return this.renderFrom(range); | ||||
|             } else { | ||||
|                 return <ErrorMessage i18nKey="Panel.Info.Range.Details.Attr.Error.Not.Range"/>; | ||||
|                 return this.renderErrorFrom("Panel.Info.Range.Details.Attr.Error.Not.Range"); | ||||
|             } | ||||
|         } | ||||
| 		return <ErrorMessage i18nKey="Panel.Info.Range.Details.Attr.Error.Unspecified"/>; | ||||
| 		return this.renderErrorFrom("Panel.Info.Range.Details.Attr.Error.Unspecified"); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user