Compare commits
	
		
			6 Commits
		
	
	
		
			7923b2d802
			...
			bb762c8273
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| bb762c8273 | |||
| 60286444fc | |||
| 50f1cb0562 | |||
| 1f4c6feafa | |||
| cc127696c5 | |||
| 89ae499d4b | 
| @ -4,6 +4,7 @@ import { LocalizationTooltipHost } from "../Localization/LocalizationTooltipHost | ||||
| import { useSetting, IMixinSettingProps } from "@Context/Setting"; | ||||
| import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | ||||
| import { AllI18nKeys } from "../Localization/Localization"; | ||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { MouseMod } from "@GLRender/ClassicRenderer"; | ||||
| import "./CommandBar.scss"; | ||||
| @ -72,7 +73,7 @@ class CommandBar extends Component<ICommandBarProps & IMixinSettingProps & IMixi | ||||
|                     iconName: "Settings", | ||||
|                     i18NKey: "Command.Bar.Setting.Info", | ||||
|                     click: () => { | ||||
|                         this.props.status ? this.props.status.popup.showPopup() : undefined; | ||||
|                         // this.props.status?.popup.showPopup(ConfirmPopup, {});
 | ||||
|                     } | ||||
|                 })} | ||||
|             </div> | ||||
|  | ||||
							
								
								
									
										67
									
								
								source/Component/ConfirmPopup/ConfirmPopup.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								source/Component/ConfirmPopup/ConfirmPopup.scss
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,67 @@ | ||||
| @import "../Theme/Theme.scss"; | ||||
| 
 | ||||
| div.confirm-root { | ||||
| 	width: 100%; | ||||
| 	height: 100%; | ||||
| 
 | ||||
| 	div.content-views { | ||||
| 		width: 100%; | ||||
| 		height: calc( 100% - 36px ); | ||||
| 		box-sizing: border-box; | ||||
| 		padding: 10px; | ||||
| 	} | ||||
| 
 | ||||
| 	div.action-view { | ||||
| 		width: 100%; | ||||
| 		height: 36px; | ||||
| 		display: flex; | ||||
| 		box-sizing: border-box; | ||||
| 		padding-right: 5px; | ||||
| 		padding-bottom: 10px; | ||||
| 		justify-content: flex-end; | ||||
| 		align-items: center; | ||||
| 
 | ||||
| 		div.action-button { | ||||
| 			height: 26px; | ||||
| 			padding: 0 10px; | ||||
| 			border-radius: 3px; | ||||
| 			margin: 0 5px; | ||||
| 			display: flex; | ||||
| 			align-items: center; | ||||
| 			cursor: pointer; | ||||
| 			user-select: none; | ||||
| 		} | ||||
| 
 | ||||
| 		div.action-button.red { | ||||
| 			color: $lt-red; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| div.dark.confirm-root { | ||||
| 
 | ||||
| 	div.action-view { | ||||
| 
 | ||||
| 		div.action-button { | ||||
| 			background-color: $lt-bg-color-lvl3-dark; | ||||
| 		} | ||||
| 
 | ||||
| 		div.action-button:hover { | ||||
| 			background-color: $lt-bg-color-lvl2-dark; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| div.light.confirm-root { | ||||
| 
 | ||||
| 	div.action-view { | ||||
| 
 | ||||
| 		div.action-button { | ||||
| 			background-color: $lt-bg-color-lvl3-light; | ||||
| 		} | ||||
| 
 | ||||
| 		div.action-button:hover { | ||||
| 			background-color: $lt-bg-color-lvl2-light; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										60
									
								
								source/Component/ConfirmPopup/ConfirmPopup.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								source/Component/ConfirmPopup/ConfirmPopup.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,60 @@ | ||||
| import { Popup } from "@Context/Popups"; | ||||
| import { ReactNode } from "react"; | ||||
| import { Message } from "@Component/Message/Message"; | ||||
| import { Theme } from "@Component/Theme/Theme"; | ||||
| import { AllI18nKeys, Localization } from "@Component/Localization/Localization"; | ||||
| import "./ConfirmPopup.scss"; | ||||
| 
 | ||||
| interface IConfirmPopupProps { | ||||
| 	titleI18N?: AllI18nKeys; | ||||
| 	infoI18n: AllI18nKeys; | ||||
| 	yesI18n?: AllI18nKeys; | ||||
| 	noI18n?: AllI18nKeys; | ||||
| 	yes?: () => any; | ||||
| 	no?: () => any; | ||||
| 	red?: "yes" | "no"; | ||||
| } | ||||
| class ConfirmPopup extends Popup<IConfirmPopupProps> { | ||||
| 
 | ||||
| 	public width: number = 300; | ||||
| 
 | ||||
| 	public height: number = 180; | ||||
| 
 | ||||
| 	public onRenderHeader(): ReactNode { | ||||
| 		return <Localization i18nKey={this.props.titleI18N ?? "Popup.Title.Confirm"}/> | ||||
| 	} | ||||
| 
 | ||||
| 	public render(): ReactNode { | ||||
| 
 | ||||
| 		const yesClassList: string[] = ["action-button", "yes-button"]; | ||||
| 		const noClassList: string[] = ["action-button", "no-button"]; | ||||
| 		if (this.props.red === "no") { | ||||
| 			noClassList.push("red"); | ||||
| 		} | ||||
| 		if (this.props.red === "yes") { | ||||
| 			yesClassList.push("red"); | ||||
| 		} | ||||
| 
 | ||||
| 		return <Theme className="confirm-root"> | ||||
| 			<div className="content-views"> | ||||
| 				<Message i18nKey={this.props.infoI18n}/> | ||||
| 			</div> | ||||
| 			<div className="action-view"> | ||||
| 				<div className={yesClassList.join(" ")} onClick={() => { | ||||
| 					this.props.yes ? this.props.yes() : null; | ||||
| 					this.close(); | ||||
| 				}}> | ||||
| 					<Localization i18nKey={this.props.yesI18n ?? "Popup.Action.Yes"}/> | ||||
| 				</div> | ||||
| 				<div className={noClassList.join(" ")} onClick={() => { | ||||
| 					this.props.no ? this.props.no() : null; | ||||
| 					this.close(); | ||||
| 				}}> | ||||
| 					<Localization i18nKey={this.props.noI18n ?? "Popup.Action.No"}/> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</Theme>; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| export { ConfirmPopup } | ||||
| @ -34,15 +34,31 @@ div.popup-layer.show-scale { | ||||
| 
 | ||||
| div.popup-mask { | ||||
|     position: absolute; | ||||
|     cursor: pointer; | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
| } | ||||
| 
 | ||||
| div.focus.popup-layer { | ||||
|     border: 0.8px solid #514feb; | ||||
| } | ||||
| 
 | ||||
| div.popup-layer { | ||||
|     position: absolute; | ||||
|     border-radius: 3px; | ||||
|     overflow: hidden; | ||||
|     transition: none; | ||||
|     box-sizing: border-box; | ||||
|     border: 0.8px solid transparent; | ||||
| 
 | ||||
|     div.popup-layer-container { | ||||
|         width: 100%; | ||||
|         height: 100%; | ||||
|         display: flex; | ||||
|     } | ||||
| 
 | ||||
|     div.popup-layer-root-content { | ||||
|         width: 100%; | ||||
|         height: 100%; | ||||
|     } | ||||
| 
 | ||||
|     div.popup-layer-header { | ||||
|         min-height: $header-height; | ||||
| @ -59,9 +75,9 @@ div.popup-layer { | ||||
|             user-select: none; | ||||
|              | ||||
|             span { | ||||
|                 padding-left: 8px; | ||||
|                 padding-left: 10px; | ||||
|                 display: inline-block; | ||||
|                 vertical-align: middle; | ||||
|                 vertical-align: bottom; | ||||
|                 white-space: nowrap; | ||||
|                 text-overflow: ellipsis; | ||||
|                 overflow: hidden; | ||||
| @ -79,12 +95,56 @@ div.popup-layer { | ||||
|             cursor: pointer; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     div.popup-layer-content { | ||||
|         height: calc( 100% - 32px ); | ||||
|         width: 100%; | ||||
|         overflow: hidden; | ||||
|     } | ||||
|      | ||||
|     div.drag-line-root.drag-line-y { | ||||
|         flex-direction: column; | ||||
|     } | ||||
| 
 | ||||
|     div.drag-line-root { | ||||
|         display: flex; | ||||
|         justify-content: center; | ||||
|         align-items: center; | ||||
|         position: relative; | ||||
| 
 | ||||
|         div.drag-line { | ||||
|             transition: all 300ms ease-in-out; | ||||
|             display: flex; | ||||
|         } | ||||
| 
 | ||||
|         div.render-drag-block-root { | ||||
|             height: 0; | ||||
|             width: 0; | ||||
|             display: flex; | ||||
|             justify-content: center; | ||||
|             align-items: center; | ||||
| 
 | ||||
|             div.render-drag-block { | ||||
|                 min-width: 5px; | ||||
|                 min-height: 5px; | ||||
|                 position: relative; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         div.drag-line:hover { | ||||
|             background-color: $lt-blue; | ||||
|         } | ||||
| 
 | ||||
|         div.drag-line.hover { | ||||
|             background-color: $lt-blue; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| div.popup-layer.dark { | ||||
|     box-shadow: 0 0 15px rgba(0, 0, 0, 0.3); | ||||
| 
 | ||||
|     div.popup-layer-header { | ||||
|         background-color: $lt-bg-color-lvl3-dark; | ||||
| 
 | ||||
|         div.header-close-icon:hover { | ||||
|             background-color: $lt-bg-color-lvl2-dark; | ||||
| @ -94,9 +154,9 @@ div.popup-layer.dark { | ||||
| } | ||||
| 
 | ||||
| div.popup-layer.light { | ||||
|     box-shadow: 0 0 15px rgba(0, 0, 0, 0.15); | ||||
| 
 | ||||
|     div.popup-layer-header { | ||||
|         background-color: $lt-bg-color-lvl3-light; | ||||
| 
 | ||||
|         div.header-close-icon:hover { | ||||
|             background-color: $lt-bg-color-lvl2-light; | ||||
|  | ||||
| @ -1,18 +1,22 @@ | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { IMixinStatusProps, useStatusWithEvent } from "@Context/Status"; | ||||
| import { BackgroundLevel, Theme } from "@Component/Theme/Theme"; | ||||
| import { Popup as PopupModel } from "@Context/Popups"; | ||||
| import { IMixinSettingProps, useSettingWithEvent } from "@Context/Setting"; | ||||
| import { BackgroundLevel, FontLevel, getClassList, Theme } from "@Component/Theme/Theme"; | ||||
| import { Popup as PopupModel, ResizeDragDirection } from "@Context/Popups"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import "./Popup.scss"; | ||||
| 
 | ||||
| interface IPopupProps {} | ||||
| 
 | ||||
| @useSettingWithEvent("themes") | ||||
| @useStatusWithEvent("popupChange") | ||||
| class Popup extends Component<IPopupProps & IMixinStatusProps> { | ||||
| class Popup extends Component<IPopupProps & IMixinStatusProps & IMixinSettingProps> { | ||||
| 
 | ||||
|     public renderMask(index?: number, click?: () => void, key?: string): ReactNode { | ||||
|         const classList: string[] = ["popup-mask", "show-fade"]; | ||||
|         return <Theme | ||||
|     private renderMask(index?: number, click?: () => void, key?: string): ReactNode { | ||||
|         const classList: string[] = ["popup-mask", "show-fade",  | ||||
|             ...getClassList({}, this.props.setting) | ||||
|         ]; | ||||
|         return <div | ||||
|             key={key} | ||||
|             onClick={click} | ||||
|             className={classList.join(" ")} | ||||
| @ -22,7 +26,7 @@ class Popup extends Component<IPopupProps & IMixinStatusProps> { | ||||
|         /> | ||||
|     } | ||||
| 
 | ||||
|     public renderRootMask(): ReactNode { | ||||
|     private renderRootMask(): ReactNode { | ||||
|         if (this.props.status) { | ||||
|             const needMask = this.props.status.popup.popups.some(popup => popup.needMask); | ||||
|             if (!needMask) return null; | ||||
| @ -38,7 +42,7 @@ class Popup extends Component<IPopupProps & IMixinStatusProps> { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public renderMaskList(): ReactNode { | ||||
|     private renderMaskList(): ReactNode { | ||||
|         if (this.props.status) { | ||||
|             return this.props.status.popup.popups | ||||
|             .filter((popup) => { | ||||
| @ -60,9 +64,22 @@ class Popup extends Component<IPopupProps & IMixinStatusProps> { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public renderHeader(popup: PopupModel): ReactNode { | ||||
|         return <div className="popup-layer-header"> | ||||
|             <div className="header-text"> | ||||
|     private renderHeader(popup: PopupModel): ReactNode { | ||||
|         return <div | ||||
|             className={getClassList({ | ||||
|                 className: "popup-layer-header", | ||||
|                 backgroundLevel: BackgroundLevel.Level3, | ||||
|                 fontLevel: FontLevel.Level3 | ||||
|             }, this.props.setting).join(" ")} | ||||
|         > | ||||
|             <div | ||||
|                 className="header-text" | ||||
|                 onMouseDown={(e) => { | ||||
|                     popup.isOnMouseDown = true; | ||||
|                     popup.lastMouseLeft = e.clientX; | ||||
|                     popup.lastMouseTop = e.clientY; | ||||
|                 }} | ||||
|             > | ||||
|                 {popup.onRenderHeader()} | ||||
|             </div> | ||||
|             <div | ||||
| @ -76,28 +93,322 @@ class Popup extends Component<IPopupProps & IMixinStatusProps> { | ||||
|         </div> | ||||
|     } | ||||
| 
 | ||||
|     public renderLayer(popup: PopupModel) { | ||||
|     private renderContent(popup: PopupModel) { | ||||
|         return <div | ||||
|             className={getClassList({ | ||||
|                 className: "popup-layer-content", | ||||
|                 backgroundLevel: BackgroundLevel.Level4, | ||||
|                 fontLevel: FontLevel.normal | ||||
|             }, this.props.setting).join(" ")} | ||||
|         > | ||||
|             {popup.render()} | ||||
|         </div> | ||||
|     } | ||||
| 
 | ||||
|     private renderDragBlock(dir: ResizeDragDirection, popup: PopupModel) { | ||||
|         return <div className="render-drag-block-root"> | ||||
|             <div | ||||
|                 draggable={false} | ||||
|                 style={{ | ||||
|                     cursor: this.mapDirToCursor.get(dir), | ||||
|                     zIndex: popup.zIndex() + 2 | ||||
|                 }} | ||||
|                 className="render-drag-block" | ||||
|                 onMouseDown={(e) => { | ||||
|                     popup.lastMouseLeft = e.clientX; | ||||
|                     popup.lastMouseTop = e.clientY; | ||||
|                     popup.resizeDragDirection = dir; | ||||
|                     popup.isResizeMouseDown = true; | ||||
|                 }} | ||||
|                 onMouseEnter={() => { | ||||
|                     popup.resizeHoverDirection = dir; | ||||
|                     this.forceUpdate(); | ||||
|                 }} | ||||
|                 onMouseLeave={() => { | ||||
|                     popup.resizeHoverDirection = undefined; | ||||
|                     this.forceUpdate(); | ||||
|                 }} | ||||
|             /> | ||||
|         </div> | ||||
|     } | ||||
| 
 | ||||
|     private mapDirToCursor = new Map<ResizeDragDirection, string>([ | ||||
|         [ResizeDragDirection.rightTop, "sw-resize"], | ||||
|         [ResizeDragDirection.rightBottom, "nw-resize"], | ||||
|         [ResizeDragDirection.leftBottom, "sw-resize"], | ||||
|         [ResizeDragDirection.LeftTop, "nw-resize"] | ||||
|     ]); | ||||
| 
 | ||||
|     private renderDragLine(dir: ResizeDragDirection, popup: PopupModel) { | ||||
|         let xy: boolean = false; | ||||
|         const dragLineCList: string[] = ["drag-line"]; | ||||
| 
 | ||||
|         if (dir === ResizeDragDirection.top || dir === ResizeDragDirection.bottom) { | ||||
|             xy = false; | ||||
|         } | ||||
|         if (dir === ResizeDragDirection.left || dir === ResizeDragDirection.right) { | ||||
|             xy = true; | ||||
|         } | ||||
|         if ( | ||||
|             ( | ||||
|                 dir === ResizeDragDirection.top &&  | ||||
|                 ( | ||||
|                     popup.resizeHoverDirection === ResizeDragDirection.LeftTop || | ||||
|                     popup.resizeHoverDirection === ResizeDragDirection.rightTop | ||||
|                 )     | ||||
|             ) || | ||||
|             ( | ||||
|                 dir === ResizeDragDirection.bottom &&  | ||||
|                 ( | ||||
|                     popup.resizeHoverDirection === ResizeDragDirection.leftBottom || | ||||
|                     popup.resizeHoverDirection === ResizeDragDirection.rightBottom | ||||
|                 )     | ||||
|             ) || | ||||
|             ( | ||||
|                 dir === ResizeDragDirection.right &&  | ||||
|                 ( | ||||
|                     popup.resizeHoverDirection === ResizeDragDirection.rightTop || | ||||
|                     popup.resizeHoverDirection === ResizeDragDirection.rightBottom | ||||
|                 )     | ||||
|             ) || | ||||
|             ( | ||||
|                 dir === ResizeDragDirection.left &&  | ||||
|                 ( | ||||
|                     popup.resizeHoverDirection === ResizeDragDirection.leftBottom || | ||||
|                     popup.resizeHoverDirection === ResizeDragDirection.LeftTop | ||||
|                 )     | ||||
|             ) | ||||
|         ) { | ||||
|             dragLineCList.push("hover") | ||||
|         } | ||||
|          | ||||
|         return <div | ||||
|             className={"drag-line-root" + (xy ? " drag-line-y" : "")} | ||||
|             style={{ | ||||
|                 width: xy ? "0" : "100%", | ||||
|                 height: xy ? "100%" : "0", | ||||
|                 zIndex: popup.zIndex() + 1 | ||||
|             }} | ||||
|         > | ||||
|             { | ||||
|                 xy && dir === ResizeDragDirection.left ? this.renderDragBlock( | ||||
|                     ResizeDragDirection.LeftTop, popup | ||||
|                 ) : null | ||||
|             } | ||||
|             { | ||||
|                 xy && dir === ResizeDragDirection.right ? this.renderDragBlock( | ||||
|                     ResizeDragDirection.rightTop, popup | ||||
|                 ) : null | ||||
|             } | ||||
|             { | ||||
|                 !xy && dir === ResizeDragDirection.bottom ? this.renderDragBlock( | ||||
|                     ResizeDragDirection.leftBottom, popup | ||||
|                 ) : null | ||||
|             } | ||||
|             <div | ||||
|                 draggable={false} | ||||
|                 className={dragLineCList.join(" ")} | ||||
|                 style={{ | ||||
|                     cursor: xy ? "e-resize" : "n-resize", | ||||
|                     minWidth: xy ? "4px" : "calc( 100% + 2px )", | ||||
|                     minHeight: xy ? "calc( 100% + 2px )" : "4px" | ||||
|                 }} | ||||
|                 onMouseDown={(e) => { | ||||
|                     popup.lastMouseLeft = e.clientX; | ||||
|                     popup.lastMouseTop = e.clientY; | ||||
|                     popup.resizeDragDirection = dir; | ||||
|                     popup.isResizeMouseDown = true; | ||||
|                 }} | ||||
|             /> | ||||
|             { | ||||
|                 !xy && dir === ResizeDragDirection.bottom ? this.renderDragBlock( | ||||
|                     ResizeDragDirection.rightBottom, popup | ||||
|                 ) : null | ||||
|             } | ||||
|         </div> | ||||
|     } | ||||
| 
 | ||||
|     private renderLayer(popup: PopupModel) { | ||||
|         const pageWidth = document.documentElement.clientWidth; | ||||
|         const pageHeight = document.documentElement.clientHeight; | ||||
|         const top = (pageHeight - popup.height) / 2; | ||||
|         const left = (pageWidth - popup.width) / 2; | ||||
|         if (isNaN(popup.top)) { | ||||
|             popup.top = (pageHeight - popup.height) / 2; | ||||
|         } | ||||
|         if (isNaN(popup.left)) { | ||||
|             popup.left = (pageWidth - popup.width) / 2; | ||||
|         } | ||||
| 
 | ||||
|         return <Theme | ||||
|             key={popup.id} | ||||
|             style={{ | ||||
|                 width: popup.width, | ||||
|                 height: popup.height, | ||||
|                 zIndex: popup.zIndex(), | ||||
|                 top: top, | ||||
|                 left: left | ||||
|                 top: popup.top, | ||||
|                 left: popup.left | ||||
|             }} | ||||
|             key={popup.id} | ||||
|             backgroundLevel={BackgroundLevel.Level4} | ||||
|             className="popup-layer show-scale" | ||||
|             className={getClassList({ | ||||
|                 className: "popup-layer show-scale", | ||||
|                 backgroundLevel: BackgroundLevel.Level4, | ||||
|             }, this.props.setting).join(" ")} | ||||
|         > | ||||
|             {this.renderDragLine(ResizeDragDirection.top, popup)} | ||||
|             <div className="popup-layer-container"> | ||||
|                 {this.renderDragLine(ResizeDragDirection.left, popup)} | ||||
|                 <div className="popup-layer-root-content"> | ||||
|                     {this.renderHeader(popup)} | ||||
|                     {this.renderContent(popup)} | ||||
|                 </div> | ||||
|                 {this.renderDragLine(ResizeDragDirection.right, popup)} | ||||
|             </div> | ||||
|             {this.renderDragLine(ResizeDragDirection.bottom, popup)} | ||||
|         </Theme> | ||||
|     } | ||||
| 
 | ||||
|     private isMouseDown: boolean = false; | ||||
| 
 | ||||
|     private handelMouseDown = () => { | ||||
|         this.isMouseDown = true; | ||||
|     } | ||||
| 
 | ||||
|     private handelMouseUp = () => { | ||||
|         this.isMouseDown = false; | ||||
|         if (this.props.status) { | ||||
|             this.props.status.popup.popups.forEach((popup) => { | ||||
|                 popup.isOnMouseDown = false; | ||||
|                 popup.resizeDragDirection = undefined; | ||||
|                 popup.isResizeMouseDown = false; | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private resize(popup: PopupModel, dis: number, dir: boolean, lsk: boolean) { | ||||
|          | ||||
|         if (dir) { | ||||
|             // Y
 | ||||
|             popup.isResizeOverFlowY = false; | ||||
|             const heightBackup = popup.height | ||||
|             const topBackup = popup.top; | ||||
|             if (lsk) { | ||||
|                 popup.height += dis; | ||||
|             } else { | ||||
|                 popup.top += dis; | ||||
|                 popup.height -= dis; | ||||
|             } | ||||
|             if (popup.height < popup.minHeight) { | ||||
|                 popup.height = heightBackup; | ||||
|                 popup.top = topBackup; | ||||
|                 popup.isResizeOverFlowY = true; | ||||
|             } | ||||
|         } else { | ||||
|             // X
 | ||||
|             popup.isResizeOverFlowX = false; | ||||
|             const leftBackup = popup.left | ||||
|             const widthBackup = popup.width; | ||||
|             if (lsk) { | ||||
|                 popup.width += dis; | ||||
|             } else { | ||||
|                 popup.left += dis; | ||||
|                 popup.width -= dis; | ||||
|             } | ||||
|             if (popup.width < popup.minWidth) { | ||||
|                 popup.width = widthBackup; | ||||
|                 popup.left = leftBackup; | ||||
|                 popup.isResizeOverFlowX = true; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private handelMouseMove = (e: MouseEvent) => { | ||||
|         let isActionSuccess: boolean = false; | ||||
|         if ( | ||||
|             this.isMouseDown && | ||||
|             this.props.status && | ||||
|             this.props.status.popup.popups.some(popup => popup.isOnMouseDown) | ||||
|         ) { | ||||
|             this.props.status.popup.popups.forEach((popup) => { | ||||
|                 if (popup.isOnMouseDown) { | ||||
|                     popup.top += e.clientY - popup.lastMouseTop; | ||||
|                     popup.left += e.clientX - popup.lastMouseLeft; | ||||
|                     popup.lastMouseLeft = e.clientX; | ||||
|                     popup.lastMouseTop = e.clientY; | ||||
|                     isActionSuccess = true; | ||||
|                     this.forceUpdate(); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|         if (this.props.status) { | ||||
|             this.props.status.popup.popups.forEach((popup) => { | ||||
|                 if (popup.resizeDragDirection) { | ||||
|                          | ||||
|                     let moveX = e.clientX - popup.lastMouseLeft; | ||||
|                     let moveY = e.clientY - popup.lastMouseTop; | ||||
|                     switch (popup.resizeDragDirection) { | ||||
| 
 | ||||
|                         case ResizeDragDirection.LeftTop: | ||||
|                             this.resize(popup, moveX, false, false); | ||||
|                             this.resize(popup, moveY, true, false); | ||||
|                             break; | ||||
| 
 | ||||
|                         case ResizeDragDirection.leftBottom: | ||||
|                             this.resize(popup, moveX, false, false); | ||||
|                             this.resize(popup, moveY, true, true); | ||||
|                             break; | ||||
| 
 | ||||
|                         case ResizeDragDirection.rightTop: | ||||
|                             this.resize(popup, moveX, false, true); | ||||
|                             this.resize(popup, moveY, true, false); | ||||
|                             break; | ||||
| 
 | ||||
|                         case ResizeDragDirection.rightBottom: | ||||
|                             this.resize(popup, moveX, false, true); | ||||
|                             this.resize(popup, moveY, true, true); | ||||
|                             break; | ||||
| 
 | ||||
|                         case ResizeDragDirection.top: | ||||
|                             this.resize(popup, moveY, true, false); | ||||
|                             break; | ||||
| 
 | ||||
|                         case ResizeDragDirection.left: | ||||
|                             this.resize(popup, moveX, false, false); | ||||
|                             break; | ||||
| 
 | ||||
|                         case ResizeDragDirection.bottom: | ||||
|                             this.resize(popup, moveY, true, true); | ||||
|                             break; | ||||
| 
 | ||||
|                         case ResizeDragDirection.right: | ||||
|                             this.resize(popup, moveX, false, true); | ||||
|                             break; | ||||
|                     } | ||||
|                     if (!popup.isResizeOverFlowX) { | ||||
|                         popup.lastMouseLeft = e.clientX; | ||||
|                     } | ||||
|                     if (!popup.isResizeOverFlowY) { | ||||
|                         popup.lastMouseTop = e.clientY; | ||||
|                     } | ||||
|                     isActionSuccess = true; | ||||
|                     this.forceUpdate(); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|         if (isActionSuccess) { | ||||
|             e.preventDefault(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public componentDidMount() { | ||||
|         window.addEventListener("mousemove", this.handelMouseMove); | ||||
|         window.addEventListener("mousedown", this.handelMouseDown); | ||||
|         window.addEventListener("mouseup", this.handelMouseUp); | ||||
|     } | ||||
| 
 | ||||
|     public componentWillUnmount() { | ||||
|         window.removeEventListener("mousemove", this.handelMouseMove); | ||||
|         window.removeEventListener("mousedown", this.handelMouseDown); | ||||
|         window.removeEventListener("mouseup", this.handelMouseUp); | ||||
|     } | ||||
| 
 | ||||
|     public render(): ReactNode { | ||||
|         return <> | ||||
|             {this.renderRootMask()} | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| import { useSetting, Themes, IMixinSettingProps } from "@Context/Setting"; | ||||
| import { useSettingWithEvent, Themes, IMixinSettingProps, Setting } from "@Context/Setting"; | ||||
| import { Component, ReactNode, DetailedHTMLProps, HTMLAttributes } from "react"; | ||||
| import "./Theme.scss"; | ||||
| 
 | ||||
| @ -23,10 +23,31 @@ interface IThemeProps { | ||||
|     backgroundLevel?: BackgroundLevel; | ||||
| } | ||||
| 
 | ||||
| function getClassList(props: IThemeProps, setting?: Setting) { | ||||
|     const classNameList: string[] = []; | ||||
| 
 | ||||
|     if (props.className) { | ||||
|         classNameList.push(props.className); | ||||
|     } | ||||
| 
 | ||||
|     const theme = setting ? setting.themes : Themes.dark; | ||||
|     classNameList.push(theme === Themes.light ? "light" : "dark"); | ||||
| 
 | ||||
|     if (props.fontLevel) { | ||||
|         classNameList.push(`font-${props.fontLevel}`); | ||||
|     } | ||||
|      | ||||
|     if (props.backgroundLevel) { | ||||
|         classNameList.push(`background-${props.backgroundLevel}`); | ||||
|     } | ||||
| 
 | ||||
|     return classNameList; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 主题切换 | ||||
|  */ | ||||
| @useSetting | ||||
| @useSettingWithEvent("themes") | ||||
| class Theme extends Component< | ||||
|     IThemeProps & IMixinSettingProps & DetailedHTMLProps< | ||||
|         HTMLAttributes<HTMLDivElement>, HTMLDivElement | ||||
| @ -52,22 +73,7 @@ class Theme extends Component< | ||||
|     public render(): ReactNode { | ||||
| 
 | ||||
|         const setting = this.props.setting; | ||||
|         const classNameList: string[] = []; | ||||
| 
 | ||||
|         if (this.props.className) { | ||||
|             classNameList.push(this.props.className); | ||||
|         } | ||||
| 
 | ||||
|         const theme = setting ? setting.themes : Themes.dark; | ||||
|         classNameList.push(theme === Themes.light ? "light" : "dark"); | ||||
| 
 | ||||
|         if (this.props.fontLevel) { | ||||
|             classNameList.push(`font-${this.props.fontLevel}`); | ||||
|         } | ||||
|          | ||||
|         if (this.props.backgroundLevel) { | ||||
|             classNameList.push(`background-${this.props.backgroundLevel}`); | ||||
|         } | ||||
|         const classNameList = getClassList(this.props, setting); | ||||
| 
 | ||||
|         const propsObj = {...this.props}; | ||||
|         delete propsObj.className; | ||||
| @ -82,4 +88,4 @@ class Theme extends Component< | ||||
| } | ||||
| 
 | ||||
| export default Theme; | ||||
| export { Theme, FontLevel, BackgroundLevel }; | ||||
| export { Theme, FontLevel, BackgroundLevel, getClassList }; | ||||
| @ -15,6 +15,10 @@ div.toggles-input { | ||||
|         cursor: pointer; | ||||
|         user-select: none; | ||||
|     } | ||||
| 
 | ||||
|     div.checkbox.red:hover { | ||||
|         color: $lt-red !important; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| div.dark.text-field-root { | ||||
|  | ||||
| @ -8,6 +8,7 @@ interface ITogglesInputProps extends ITextFieldProps { | ||||
|     onIconName?: string; | ||||
|     offIconName?: string; | ||||
|     valueChange?: (value: boolean) => any; | ||||
|     red?: boolean; | ||||
| } | ||||
| 
 | ||||
| class TogglesInput extends Component<ITogglesInputProps> { | ||||
| @ -20,7 +21,7 @@ class TogglesInput extends Component<ITogglesInputProps> { | ||||
|             customStyle | ||||
|         > | ||||
|             <div | ||||
|                 className="checkbox" | ||||
|                 className={"checkbox" + (this.props.red ? " red" : "")} | ||||
|                 style={{ | ||||
|                     cursor: this.props.disableI18n ? "not-allowed" : "pointer" | ||||
|                 }} | ||||
|  | ||||
| @ -1,25 +1,48 @@ | ||||
| import { ReactNode, createElement } from "react"; | ||||
| import { Emitter } from "@Model/Emitter"; | ||||
| import { Localization } from "@Component/Localization/Localization"; | ||||
| import { IAnyObject } from "@Model/Renderer"; | ||||
| 
 | ||||
| type IPopupConstructor = new (controller: PopupController, id: string) => Popup; | ||||
| enum ResizeDragDirection { | ||||
|     top = 1, | ||||
|     rightTop = 2, | ||||
|     right = 3, | ||||
|     rightBottom = 4, | ||||
|     bottom = 5, | ||||
|     leftBottom = 6, | ||||
|     left = 7, | ||||
|     LeftTop = 8 | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 弹窗类型 | ||||
|  */ | ||||
| class Popup { | ||||
| class Popup<P extends IAnyObject = IAnyObject> { | ||||
| 
 | ||||
|     public props: P; | ||||
| 
 | ||||
|     public constructor(props: P) { | ||||
|         this.props = props; | ||||
|     } | ||||
| 
 | ||||
|     public zIndex() { | ||||
|         return this.index * 2 + this.controller.zIndex; | ||||
|         return this.index * 5 + this.controller.zIndex; | ||||
|     } | ||||
| 
 | ||||
|     public width: number = 300; | ||||
| 
 | ||||
|     public height: number = 200; | ||||
| 
 | ||||
|     public top: number = 0; | ||||
| 
 | ||||
|     public left: number = 0; | ||||
|     public minWidth: number = 300; | ||||
|     public minHeight: number = 200; | ||||
|     public top: number = NaN; | ||||
|     public left: number = NaN; | ||||
|     public lastMouseTop: number = 0; | ||||
|     public lastMouseLeft: number = 0; | ||||
|     public isOnMouseDown: boolean = false; | ||||
|     public resizeHoverDirection?: ResizeDragDirection; | ||||
|     public resizeDragDirection?: ResizeDragDirection; | ||||
|     public isResizeMouseDown: boolean = false; | ||||
|     public isResizeOverFlowX: boolean = false; | ||||
|     public isResizeOverFlowY: boolean = false; | ||||
| 
 | ||||
|     /** | ||||
|      * 是否关闭 | ||||
| @ -39,23 +62,18 @@ class Popup { | ||||
|     /** | ||||
|      * 唯一标识符 | ||||
|      */ | ||||
|     public id: string; | ||||
|     public id: string = ""; | ||||
| 
 | ||||
|     /** | ||||
|      * 控制器 | ||||
|      */ | ||||
|     public controller: PopupController; | ||||
|     public controller: PopupController = undefined as any; | ||||
| 
 | ||||
|     /** | ||||
|      * 渲染层级 | ||||
|      */ | ||||
|     public index: number = Infinity; | ||||
| 
 | ||||
|     /** | ||||
|      * react 节点 | ||||
|      */ | ||||
|     public reactNode: ReactNode; | ||||
| 
 | ||||
|     /** | ||||
|      * 渲染标题 | ||||
|      */ | ||||
| @ -63,13 +81,6 @@ class Popup { | ||||
|         return createElement(Localization, {i18nKey: "Popup.Title.Unnamed"}); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 渲染函数 | ||||
|      */ | ||||
|     public onRender(p: Popup): ReactNode { | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 关闭回调 | ||||
|      */ | ||||
| @ -81,15 +92,14 @@ class Popup { | ||||
|      * 渲染节点 | ||||
|      */ | ||||
|     public render(): ReactNode { | ||||
|         this.reactNode = this.onRender(this); | ||||
|         return this.reactNode; | ||||
|         return null; | ||||
|     }; | ||||
| 
 | ||||
|     public close() { | ||||
|     public close(): Popup | undefined { | ||||
|         return this.controller.closePopup(this); | ||||
|     } | ||||
| 
 | ||||
|     public constructor(controller: PopupController, id: string) { | ||||
|     public init(controller: PopupController, id: string) { | ||||
|         this.controller = controller; | ||||
|         this.id = id; | ||||
|     } | ||||
| @ -134,8 +144,16 @@ class PopupController extends Emitter<IPopupControllerEvent> { | ||||
|     /** | ||||
|      * 实例化并开启一个弹窗 | ||||
|      */ | ||||
|     public showPopup<P extends IPopupConstructor>(popup?: P): Popup { | ||||
|         let newPopup = new (popup ?? Popup)(this, `P-${this.idIndex ++}`); | ||||
|     public showPopup<P extends IAnyObject, T extends Popup<P>>( | ||||
|         popup: (new (props: P) => T) | Popup<P>, props: P | ||||
|     ): Popup<P> { | ||||
|         let newPopup: Popup<P>; | ||||
|         if (popup instanceof Popup) { | ||||
|             newPopup = popup; | ||||
|         } else { | ||||
|             newPopup = new (popup ?? Popup)(props); | ||||
|         } | ||||
|         newPopup.init(this, `P-${this.idIndex ++}`); | ||||
|         this.popups.push(newPopup); | ||||
|         this.sortPopup(); | ||||
|         return newPopup; | ||||
| @ -172,4 +190,4 @@ class PopupController extends Emitter<IPopupControllerEvent> { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export { Popup, PopupController } | ||||
| export { Popup, PopupController, ResizeDragDirection } | ||||
| @ -45,6 +45,12 @@ const EN_US = { | ||||
|     "Panel.Title.Group.Details.View": "Group", | ||||
|     "Panel.Info.Group.Details.View": "Edit view group attributes", | ||||
|     "Popup.Title.Unnamed": "Popup message", | ||||
|     "Popup.Title.Confirm": "Confirm message", | ||||
|     "Popup.Action.Yes": "Confirm", | ||||
|     "Popup.Action.No": "Cancel", | ||||
|     "Popup.Action.Objects.Confirm.Title": "Confirm Delete", | ||||
|     "Popup.Action.Objects.Confirm.Delete": "Delete", | ||||
|     "Popup.Delete.Objects.Confirm": "Are you sure you want to delete this object(s)? The object is deleted and cannot be recalled.", | ||||
|     "Build.In.Label.Name.All.Group": "All group", | ||||
|     "Build.In.Label.Name.All.Range": "All range", | ||||
|     "Common.No.Data": "No Data", | ||||
|  | ||||
| @ -45,6 +45,12 @@ const ZH_CN = { | ||||
|     "Panel.Title.Group.Details.View": "群", | ||||
|     "Panel.Info.Group.Details.View": "编辑查看群属性", | ||||
|     "Popup.Title.Unnamed": "弹窗消息", | ||||
|     "Popup.Title.Confirm": "确认消息", | ||||
|     "Popup.Action.Yes": "确定", | ||||
|     "Popup.Action.No": "取消", | ||||
|     "Popup.Action.Objects.Confirm.Title": "删除确认", | ||||
|     "Popup.Action.Objects.Confirm.Delete": "删除", | ||||
|     "Popup.Delete.Objects.Confirm": "你确定要删除这个(些)对象吗?对象被删除将无法撤回。", | ||||
|     "Build.In.Label.Name.All.Group": "全部群", | ||||
|     "Build.In.Label.Name.All.Range": "全部范围", | ||||
|     "Common.No.Data": "暂无数据", | ||||
|  | ||||
| @ -10,6 +10,7 @@ import { Group, GenMod } from "@Model/Group"; | ||||
| import { AllI18nKeys } from "@Component/Localization/Localization"; | ||||
| import { ComboInput, IDisplayItem } from "@Component/ComboInput/ComboInput"; | ||||
| import { ObjectPicker } from "@Component/ObjectPicker/ObjectPicker"; | ||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| import "./GroupDetails.scss"; | ||||
| 
 | ||||
| interface IGroupDetailsProps {} | ||||
| @ -88,12 +89,21 @@ class GroupDetails extends Component<IGroupDetailsProps & IMixinStatusProps> { | ||||
|             /> | ||||
| 
 | ||||
| 			<TogglesInput | ||||
| 				keyI18n="Common.Attr.Key.Delete" | ||||
| 				keyI18n="Common.Attr.Key.Delete" red | ||||
| 				onIconName="delete" offIconName="delete" | ||||
| 				valueChange={() => { | ||||
| 					if (this.props.status) { | ||||
| 						this.props.status.model.deleteObject([group]); | ||||
| 						this.props.status.setFocusObject(new Set()); | ||||
|                         const status = this.props.status; | ||||
| 						status.popup.showPopup(ConfirmPopup, { | ||||
| 							infoI18n: "Popup.Delete.Objects.Confirm", | ||||
| 							titleI18N: "Popup.Action.Objects.Confirm.Title", | ||||
| 							yesI18n: "Popup.Action.Objects.Confirm.Delete", | ||||
| 							red: "yes", | ||||
| 							yes: () => { | ||||
| 								status.model.deleteObject([group]); | ||||
| 						        status.setFocusObject(new Set()); | ||||
| 							} | ||||
| 						}) | ||||
| 					} | ||||
| 				}} | ||||
| 			/> | ||||
| @ -147,7 +157,7 @@ class GroupDetails extends Component<IGroupDetailsProps & IMixinStatusProps> { | ||||
|             /> | ||||
| 
 | ||||
|             <TogglesInput | ||||
| 				keyI18n="Common.Attr.Key.Generation" | ||||
| 				keyI18n="Common.Attr.Key.Kill.Random" | ||||
| 				onIconName="RemoveFilter" offIconName="RemoveFilter" | ||||
| 				valueChange={() => { | ||||
| 					group.killIndividuals() | ||||
|  | ||||
| @ -5,6 +5,7 @@ import { Message } from "@Component/Message/Message"; | ||||
| import { ColorInput } from "@Component/ColorInput/ColorInput"; | ||||
| import { Label } from "@Model/Label"; | ||||
| import { TogglesInput } from "@Component/TogglesInput/TogglesInput"; | ||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| import "./LabelDetails.scss"; | ||||
| 
 | ||||
| @useStatusWithEvent("focusLabelChange", "labelAttrChange", "labelChange") | ||||
| @ -27,10 +28,21 @@ class LabelDetails extends Component<IMixinStatusProps> { | ||||
|                 } | ||||
|             }}/> | ||||
| 
 | ||||
|             <TogglesInput keyI18n="Common.Attr.Key.Delete" onIconName="delete" offIconName="delete" valueChange={() => { | ||||
|             <TogglesInput | ||||
|                 keyI18n="Common.Attr.Key.Delete" onIconName="delete" red | ||||
|                 offIconName="delete" valueChange={() => { | ||||
|                 if (this.props.status) { | ||||
|                     this.props.status.model.deleteLabel(label); | ||||
|                     this.props.status.setLabelObject(); | ||||
|                     const status = this.props.status; | ||||
|                     status.popup.showPopup(ConfirmPopup, { | ||||
|                         infoI18n: "Popup.Delete.Objects.Confirm", | ||||
|                         titleI18N: "Popup.Action.Objects.Confirm.Title", | ||||
|                         yesI18n: "Popup.Action.Objects.Confirm.Delete", | ||||
|                         red: "yes", | ||||
|                         yes: () => { | ||||
|                             status.model.deleteLabel(label); | ||||
|                             status.setLabelObject(); | ||||
|                         } | ||||
|                     }) | ||||
|                 } | ||||
|             }}/> | ||||
| 
 | ||||
|  | ||||
| @ -4,6 +4,7 @@ import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | ||||
| import { useSetting, IMixinSettingProps } from "@Context/Setting"; | ||||
| import { Label } from "@Model/Label"; | ||||
| import { Message } from "@Component/Message/Message"; | ||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| import "./LabelList.scss"; | ||||
| 
 | ||||
| interface ILabelListProps { | ||||
| @ -47,8 +48,17 @@ class LabelList extends Component<ILabelListProps & IMixinStatusProps & IMixinSe | ||||
|                 }} | ||||
|                 deleteLabel={(label) => { | ||||
|                     if (this.props.status) { | ||||
|                         this.props.status.model.deleteLabel(label); | ||||
|                         this.props.status.setLabelObject(); | ||||
|                         const status = this.props.status; | ||||
|                         status.popup.showPopup(ConfirmPopup, { | ||||
|                             infoI18n: "Popup.Delete.Objects.Confirm", | ||||
|                             titleI18N: "Popup.Action.Objects.Confirm.Title", | ||||
|                             yesI18n: "Popup.Action.Objects.Confirm.Delete", | ||||
|                             red: "yes", | ||||
|                             yes: () => { | ||||
|                                 status.model.deleteLabel(label); | ||||
|                                 status.setLabelObject(); | ||||
|                             } | ||||
|                         }) | ||||
|                     } | ||||
|                     this.labelInnerClick = true; | ||||
|                 }} | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| import { BackgroundLevel, FontLevel, Theme } from "@Component/Theme/Theme"; | ||||
| import { useStatus, IMixinStatusProps } from "../../Context/Status"; | ||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { ObjectID } from "@Model/Renderer"; | ||||
| @ -54,15 +55,24 @@ class ObjectCommand extends Component<IMixinStatusProps> { | ||||
| 				<Icon iconName="CubeShape"></Icon> | ||||
| 			</div> | ||||
| 			<div | ||||
| 				className="command-item" | ||||
| 				className="command-item red" | ||||
| 				onClick={() => { | ||||
| 					if (this.props.status) { | ||||
| 					if (this.props.status && this.props.status.focusObject.size > 0) { | ||||
| 						const status = this.props.status; | ||||
| 						status.popup.showPopup(ConfirmPopup, { | ||||
| 							infoI18n: "Popup.Delete.Objects.Confirm", | ||||
| 							titleI18N: "Popup.Action.Objects.Confirm.Title", | ||||
| 							yesI18n: "Popup.Action.Objects.Confirm.Delete", | ||||
| 							red: "yes", | ||||
| 							yes: () => { | ||||
| 								let deleteId: ObjectID[] = []; | ||||
| 						this.props.status.focusObject.forEach((obj) => { | ||||
| 								status.focusObject.forEach((obj) => { | ||||
| 									deleteId.push(obj); | ||||
| 								}) | ||||
| 						this.props.status.model.deleteObject(deleteId); | ||||
| 						this.props.status.setFocusObject(new Set<ObjectID>()); | ||||
| 								status.model.deleteObject(deleteId); | ||||
| 								status.setFocusObject(new Set<ObjectID>()); | ||||
| 							} | ||||
| 						}) | ||||
| 					} | ||||
| 				}} | ||||
| 			> | ||||
|  | ||||
| @ -59,6 +59,10 @@ div.object-list-command-bar { | ||||
|         user-select: none; | ||||
|         cursor: pointer; | ||||
|     } | ||||
| 
 | ||||
|     div.command-item.red:hover { | ||||
|         color: $lt-red; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| div.dark.object-list-command-bar { | ||||
|  | ||||
| @ -1,13 +1,13 @@ | ||||
| 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 { Message } from "@Component/Message/Message"; | ||||
| import { Range } from "@Model/Range"; | ||||
| import { ObjectID } from "@Model/Renderer"; | ||||
| import { ColorInput } from "@Component/ColorInput/ColorInput"; | ||||
| import { TogglesInput } from "@Component/TogglesInput/TogglesInput"; | ||||
| import { LabelPicker } from "@Component/LabelPicker/LabelPicker"; | ||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| import "./RangeDetails.scss"; | ||||
| 
 | ||||
| @useStatusWithEvent("rangeAttrChange", "focusObjectChange", "rangeLabelChange") | ||||
| @ -53,12 +53,21 @@ class RangeDetails extends Component<IMixinStatusProps> { | ||||
|             /> | ||||
| 
 | ||||
|             <TogglesInput | ||||
| 				keyI18n="Common.Attr.Key.Delete" | ||||
| 				keyI18n="Common.Attr.Key.Delete" red | ||||
| 				onIconName="delete" offIconName="delete" | ||||
| 				valueChange={() => { | ||||
|                     if (this.props.status) { | ||||
| 						this.props.status.model.deleteObject([range]); | ||||
| 						this.props.status.setFocusObject(new Set()); | ||||
|                         const status = this.props.status; | ||||
| 						status.popup.showPopup(ConfirmPopup, { | ||||
| 							infoI18n: "Popup.Delete.Objects.Confirm", | ||||
| 							titleI18N: "Popup.Action.Objects.Confirm.Title", | ||||
| 							yesI18n: "Popup.Action.Objects.Confirm.Delete", | ||||
| 							red: "yes", | ||||
| 							yes: () => { | ||||
| 								status.model.deleteObject([range]); | ||||
| 						        status.setFocusObject(new Set()); | ||||
| 							} | ||||
| 						}) | ||||
| 					} | ||||
| 				}} | ||||
| 			/> | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user