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 { useSetting, IMixinSettingProps } from "@Context/Setting"; | ||||||
| import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | ||||||
| import { AllI18nKeys } from "../Localization/Localization"; | import { AllI18nKeys } from "../Localization/Localization"; | ||||||
|  | import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||||
| import { Component, ReactNode } from "react"; | import { Component, ReactNode } from "react"; | ||||||
| import { MouseMod } from "@GLRender/ClassicRenderer"; | import { MouseMod } from "@GLRender/ClassicRenderer"; | ||||||
| import "./CommandBar.scss"; | import "./CommandBar.scss"; | ||||||
| @ -72,7 +73,7 @@ class CommandBar extends Component<ICommandBarProps & IMixinSettingProps & IMixi | |||||||
|                     iconName: "Settings", |                     iconName: "Settings", | ||||||
|                     i18NKey: "Command.Bar.Setting.Info", |                     i18NKey: "Command.Bar.Setting.Info", | ||||||
|                     click: () => { |                     click: () => { | ||||||
|                         this.props.status ? this.props.status.popup.showPopup() : undefined; |                         // this.props.status?.popup.showPopup(ConfirmPopup, {});
 | ||||||
|                     } |                     } | ||||||
|                 })} |                 })} | ||||||
|             </div> |             </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 { | div.popup-mask { | ||||||
|     position: absolute; |     position: absolute; | ||||||
|     cursor: pointer; |  | ||||||
|     width: 100%; |     width: 100%; | ||||||
|     height: 100%; |     height: 100%; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | div.focus.popup-layer { | ||||||
|  |     border: 0.8px solid #514feb; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| div.popup-layer { | div.popup-layer { | ||||||
|     position: absolute; |     position: absolute; | ||||||
|     border-radius: 3px; |     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 { |     div.popup-layer-header { | ||||||
|         min-height: $header-height; |         min-height: $header-height; | ||||||
| @ -59,9 +75,9 @@ div.popup-layer { | |||||||
|             user-select: none; |             user-select: none; | ||||||
|              |              | ||||||
|             span { |             span { | ||||||
|                 padding-left: 8px; |                 padding-left: 10px; | ||||||
|                 display: inline-block; |                 display: inline-block; | ||||||
|                 vertical-align: middle; |                 vertical-align: bottom; | ||||||
|                 white-space: nowrap; |                 white-space: nowrap; | ||||||
|                 text-overflow: ellipsis; |                 text-overflow: ellipsis; | ||||||
|                 overflow: hidden; |                 overflow: hidden; | ||||||
| @ -79,12 +95,56 @@ div.popup-layer { | |||||||
|             cursor: pointer; |             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 { | div.popup-layer.dark { | ||||||
|  |     box-shadow: 0 0 15px rgba(0, 0, 0, 0.3); | ||||||
| 
 | 
 | ||||||
|     div.popup-layer-header { |     div.popup-layer-header { | ||||||
|         background-color: $lt-bg-color-lvl3-dark; |  | ||||||
| 
 | 
 | ||||||
|         div.header-close-icon:hover { |         div.header-close-icon:hover { | ||||||
|             background-color: $lt-bg-color-lvl2-dark; |             background-color: $lt-bg-color-lvl2-dark; | ||||||
| @ -94,9 +154,9 @@ div.popup-layer.dark { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| div.popup-layer.light { | div.popup-layer.light { | ||||||
|  |     box-shadow: 0 0 15px rgba(0, 0, 0, 0.15); | ||||||
| 
 | 
 | ||||||
|     div.popup-layer-header { |     div.popup-layer-header { | ||||||
|         background-color: $lt-bg-color-lvl3-light; |  | ||||||
| 
 | 
 | ||||||
|         div.header-close-icon:hover { |         div.header-close-icon:hover { | ||||||
|             background-color: $lt-bg-color-lvl2-light; |             background-color: $lt-bg-color-lvl2-light; | ||||||
|  | |||||||
| @ -1,18 +1,22 @@ | |||||||
| import { Component, ReactNode } from "react"; | import { Component, ReactNode } from "react"; | ||||||
| import { IMixinStatusProps, useStatusWithEvent } from "@Context/Status"; | import { IMixinStatusProps, useStatusWithEvent } from "@Context/Status"; | ||||||
| import { BackgroundLevel, Theme } from "@Component/Theme/Theme"; | import { IMixinSettingProps, useSettingWithEvent } from "@Context/Setting"; | ||||||
| import { Popup as PopupModel } from "@Context/Popups"; | import { BackgroundLevel, FontLevel, getClassList, Theme } from "@Component/Theme/Theme"; | ||||||
|  | import { Popup as PopupModel, ResizeDragDirection } from "@Context/Popups"; | ||||||
| import { Icon } from "@fluentui/react"; | import { Icon } from "@fluentui/react"; | ||||||
| import "./Popup.scss"; | import "./Popup.scss"; | ||||||
| 
 | 
 | ||||||
| interface IPopupProps {} | interface IPopupProps {} | ||||||
| 
 | 
 | ||||||
|  | @useSettingWithEvent("themes") | ||||||
| @useStatusWithEvent("popupChange") | @useStatusWithEvent("popupChange") | ||||||
| class Popup extends Component<IPopupProps & IMixinStatusProps> { | class Popup extends Component<IPopupProps & IMixinStatusProps & IMixinSettingProps> { | ||||||
| 
 | 
 | ||||||
|     public renderMask(index?: number, click?: () => void, key?: string): ReactNode { |     private renderMask(index?: number, click?: () => void, key?: string): ReactNode { | ||||||
|         const classList: string[] = ["popup-mask", "show-fade"]; |         const classList: string[] = ["popup-mask", "show-fade",  | ||||||
|         return <Theme |             ...getClassList({}, this.props.setting) | ||||||
|  |         ]; | ||||||
|  |         return <div | ||||||
|             key={key} |             key={key} | ||||||
|             onClick={click} |             onClick={click} | ||||||
|             className={classList.join(" ")} |             className={classList.join(" ")} | ||||||
| @ -22,7 +26,7 @@ class Popup extends Component<IPopupProps & IMixinStatusProps> { | |||||||
|         /> |         /> | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public renderRootMask(): ReactNode { |     private renderRootMask(): ReactNode { | ||||||
|         if (this.props.status) { |         if (this.props.status) { | ||||||
|             const needMask = this.props.status.popup.popups.some(popup => popup.needMask); |             const needMask = this.props.status.popup.popups.some(popup => popup.needMask); | ||||||
|             if (!needMask) return null; |             if (!needMask) return null; | ||||||
| @ -38,7 +42,7 @@ class Popup extends Component<IPopupProps & IMixinStatusProps> { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public renderMaskList(): ReactNode { |     private renderMaskList(): ReactNode { | ||||||
|         if (this.props.status) { |         if (this.props.status) { | ||||||
|             return this.props.status.popup.popups |             return this.props.status.popup.popups | ||||||
|             .filter((popup) => { |             .filter((popup) => { | ||||||
| @ -60,9 +64,22 @@ class Popup extends Component<IPopupProps & IMixinStatusProps> { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public renderHeader(popup: PopupModel): ReactNode { |     private renderHeader(popup: PopupModel): ReactNode { | ||||||
|         return <div className="popup-layer-header"> |         return <div | ||||||
|             <div className="header-text"> |             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()} |                 {popup.onRenderHeader()} | ||||||
|             </div> |             </div> | ||||||
|             <div |             <div | ||||||
| @ -76,28 +93,322 @@ class Popup extends Component<IPopupProps & IMixinStatusProps> { | |||||||
|         </div> |         </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 pageWidth = document.documentElement.clientWidth; | ||||||
|         const pageHeight = document.documentElement.clientHeight; |         const pageHeight = document.documentElement.clientHeight; | ||||||
|         const top = (pageHeight - popup.height) / 2; |         if (isNaN(popup.top)) { | ||||||
|         const left = (pageWidth - popup.width) / 2; |             popup.top = (pageHeight - popup.height) / 2; | ||||||
|  |         } | ||||||
|  |         if (isNaN(popup.left)) { | ||||||
|  |             popup.left = (pageWidth - popup.width) / 2; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         return <Theme |         return <Theme | ||||||
|  |             key={popup.id} | ||||||
|             style={{ |             style={{ | ||||||
|                 width: popup.width, |                 width: popup.width, | ||||||
|                 height: popup.height, |                 height: popup.height, | ||||||
|                 zIndex: popup.zIndex(), |                 zIndex: popup.zIndex(), | ||||||
|                 top: top, |                 top: popup.top, | ||||||
|                 left: left |                 left: popup.left | ||||||
|             }} |             }} | ||||||
|             key={popup.id} |             className={getClassList({ | ||||||
|             backgroundLevel={BackgroundLevel.Level4} |                 className: "popup-layer show-scale", | ||||||
|             className="popup-layer show-scale" |                 backgroundLevel: BackgroundLevel.Level4, | ||||||
|  |             }, this.props.setting).join(" ")} | ||||||
|         > |         > | ||||||
|             {this.renderHeader(popup)} |             {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> |         </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 { |     public render(): ReactNode { | ||||||
|         return <> |         return <> | ||||||
|             {this.renderRootMask()} |             {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 { Component, ReactNode, DetailedHTMLProps, HTMLAttributes } from "react"; | ||||||
| import "./Theme.scss"; | import "./Theme.scss"; | ||||||
| 
 | 
 | ||||||
| @ -23,10 +23,31 @@ interface IThemeProps { | |||||||
|     backgroundLevel?: BackgroundLevel; |     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< | class Theme extends Component< | ||||||
|     IThemeProps & IMixinSettingProps & DetailedHTMLProps< |     IThemeProps & IMixinSettingProps & DetailedHTMLProps< | ||||||
|         HTMLAttributes<HTMLDivElement>, HTMLDivElement |         HTMLAttributes<HTMLDivElement>, HTMLDivElement | ||||||
| @ -52,22 +73,7 @@ class Theme extends Component< | |||||||
|     public render(): ReactNode { |     public render(): ReactNode { | ||||||
| 
 | 
 | ||||||
|         const setting = this.props.setting; |         const setting = this.props.setting; | ||||||
|         const classNameList: string[] = []; |         const classNameList = getClassList(this.props, setting); | ||||||
| 
 |  | ||||||
|         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 propsObj = {...this.props}; |         const propsObj = {...this.props}; | ||||||
|         delete propsObj.className; |         delete propsObj.className; | ||||||
| @ -82,4 +88,4 @@ class Theme extends Component< | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export default Theme; | export default Theme; | ||||||
| export { Theme, FontLevel, BackgroundLevel }; | export { Theme, FontLevel, BackgroundLevel, getClassList }; | ||||||
| @ -15,6 +15,10 @@ div.toggles-input { | |||||||
|         cursor: pointer; |         cursor: pointer; | ||||||
|         user-select: none; |         user-select: none; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     div.checkbox.red:hover { | ||||||
|  |         color: $lt-red !important; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| div.dark.text-field-root { | div.dark.text-field-root { | ||||||
|  | |||||||
| @ -8,6 +8,7 @@ interface ITogglesInputProps extends ITextFieldProps { | |||||||
|     onIconName?: string; |     onIconName?: string; | ||||||
|     offIconName?: string; |     offIconName?: string; | ||||||
|     valueChange?: (value: boolean) => any; |     valueChange?: (value: boolean) => any; | ||||||
|  |     red?: boolean; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class TogglesInput extends Component<ITogglesInputProps> { | class TogglesInput extends Component<ITogglesInputProps> { | ||||||
| @ -20,7 +21,7 @@ class TogglesInput extends Component<ITogglesInputProps> { | |||||||
|             customStyle |             customStyle | ||||||
|         > |         > | ||||||
|             <div |             <div | ||||||
|                 className="checkbox" |                 className={"checkbox" + (this.props.red ? " red" : "")} | ||||||
|                 style={{ |                 style={{ | ||||||
|                     cursor: this.props.disableI18n ? "not-allowed" : "pointer" |                     cursor: this.props.disableI18n ? "not-allowed" : "pointer" | ||||||
|                 }} |                 }} | ||||||
|  | |||||||
| @ -1,25 +1,48 @@ | |||||||
| import { ReactNode, createElement } from "react"; | import { ReactNode, createElement } from "react"; | ||||||
| import { Emitter } from "@Model/Emitter"; | import { Emitter } from "@Model/Emitter"; | ||||||
| import { Localization } from "@Component/Localization/Localization"; | 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() { |     public zIndex() { | ||||||
|         return this.index * 2 + this.controller.zIndex; |         return this.index * 5 + this.controller.zIndex; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public width: number = 300; |     public width: number = 300; | ||||||
| 
 |  | ||||||
|     public height: number = 200; |     public height: number = 200; | ||||||
| 
 |     public minWidth: number = 300; | ||||||
|     public top: number = 0; |     public minHeight: number = 200; | ||||||
| 
 |     public top: number = NaN; | ||||||
|     public left: number = 0; |     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; |     public index: number = Infinity; | ||||||
| 
 | 
 | ||||||
|     /** |  | ||||||
|      * react 节点 |  | ||||||
|      */ |  | ||||||
|     public reactNode: ReactNode; |  | ||||||
| 
 |  | ||||||
|     /** |     /** | ||||||
|      * 渲染标题 |      * 渲染标题 | ||||||
|      */ |      */ | ||||||
| @ -63,13 +81,6 @@ class Popup { | |||||||
|         return createElement(Localization, {i18nKey: "Popup.Title.Unnamed"}); |         return createElement(Localization, {i18nKey: "Popup.Title.Unnamed"}); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |  | ||||||
|      * 渲染函数 |  | ||||||
|      */ |  | ||||||
|     public onRender(p: Popup): ReactNode { |  | ||||||
|         return null; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |     /** | ||||||
|      * 关闭回调 |      * 关闭回调 | ||||||
|      */ |      */ | ||||||
| @ -81,15 +92,14 @@ class Popup { | |||||||
|      * 渲染节点 |      * 渲染节点 | ||||||
|      */ |      */ | ||||||
|     public render(): ReactNode { |     public render(): ReactNode { | ||||||
|         this.reactNode = this.onRender(this); |         return null; | ||||||
|         return this.reactNode; |  | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     public close() { |     public close(): Popup | undefined { | ||||||
|         return this.controller.closePopup(this); |         return this.controller.closePopup(this); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public constructor(controller: PopupController, id: string) { |     public init(controller: PopupController, id: string) { | ||||||
|         this.controller = controller; |         this.controller = controller; | ||||||
|         this.id = id; |         this.id = id; | ||||||
|     } |     } | ||||||
| @ -134,8 +144,16 @@ class PopupController extends Emitter<IPopupControllerEvent> { | |||||||
|     /** |     /** | ||||||
|      * 实例化并开启一个弹窗 |      * 实例化并开启一个弹窗 | ||||||
|      */ |      */ | ||||||
|     public showPopup<P extends IPopupConstructor>(popup?: P): Popup { |     public showPopup<P extends IAnyObject, T extends Popup<P>>( | ||||||
|         let newPopup = new (popup ?? Popup)(this, `P-${this.idIndex ++}`); |         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.popups.push(newPopup); | ||||||
|         this.sortPopup(); |         this.sortPopup(); | ||||||
|         return newPopup; |         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.Title.Group.Details.View": "Group", | ||||||
|     "Panel.Info.Group.Details.View": "Edit view group attributes", |     "Panel.Info.Group.Details.View": "Edit view group attributes", | ||||||
|     "Popup.Title.Unnamed": "Popup message", |     "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.Group": "All group", | ||||||
|     "Build.In.Label.Name.All.Range": "All range", |     "Build.In.Label.Name.All.Range": "All range", | ||||||
|     "Common.No.Data": "No Data", |     "Common.No.Data": "No Data", | ||||||
|  | |||||||
| @ -45,6 +45,12 @@ const ZH_CN = { | |||||||
|     "Panel.Title.Group.Details.View": "群", |     "Panel.Title.Group.Details.View": "群", | ||||||
|     "Panel.Info.Group.Details.View": "编辑查看群属性", |     "Panel.Info.Group.Details.View": "编辑查看群属性", | ||||||
|     "Popup.Title.Unnamed": "弹窗消息", |     "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.Group": "全部群", | ||||||
|     "Build.In.Label.Name.All.Range": "全部范围", |     "Build.In.Label.Name.All.Range": "全部范围", | ||||||
|     "Common.No.Data": "暂无数据", |     "Common.No.Data": "暂无数据", | ||||||
|  | |||||||
| @ -10,6 +10,7 @@ import { Group, GenMod } from "@Model/Group"; | |||||||
| import { AllI18nKeys } from "@Component/Localization/Localization"; | import { AllI18nKeys } from "@Component/Localization/Localization"; | ||||||
| import { ComboInput, IDisplayItem } from "@Component/ComboInput/ComboInput"; | import { ComboInput, IDisplayItem } from "@Component/ComboInput/ComboInput"; | ||||||
| import { ObjectPicker } from "@Component/ObjectPicker/ObjectPicker"; | import { ObjectPicker } from "@Component/ObjectPicker/ObjectPicker"; | ||||||
|  | import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||||
| import "./GroupDetails.scss"; | import "./GroupDetails.scss"; | ||||||
| 
 | 
 | ||||||
| interface IGroupDetailsProps {} | interface IGroupDetailsProps {} | ||||||
| @ -88,12 +89,21 @@ class GroupDetails extends Component<IGroupDetailsProps & IMixinStatusProps> { | |||||||
|             /> |             /> | ||||||
| 
 | 
 | ||||||
| 			<TogglesInput | 			<TogglesInput | ||||||
| 				keyI18n="Common.Attr.Key.Delete" | 				keyI18n="Common.Attr.Key.Delete" red | ||||||
| 				onIconName="delete" offIconName="delete" | 				onIconName="delete" offIconName="delete" | ||||||
| 				valueChange={() => { | 				valueChange={() => { | ||||||
| 					if (this.props.status) { | 					if (this.props.status) { | ||||||
| 						this.props.status.model.deleteObject([group]); |                         const status = this.props.status; | ||||||
| 						this.props.status.setFocusObject(new Set()); | 						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 |             <TogglesInput | ||||||
| 				keyI18n="Common.Attr.Key.Generation" | 				keyI18n="Common.Attr.Key.Kill.Random" | ||||||
| 				onIconName="RemoveFilter" offIconName="RemoveFilter" | 				onIconName="RemoveFilter" offIconName="RemoveFilter" | ||||||
| 				valueChange={() => { | 				valueChange={() => { | ||||||
| 					group.killIndividuals() | 					group.killIndividuals() | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ import { Message } from "@Component/Message/Message"; | |||||||
| import { ColorInput } from "@Component/ColorInput/ColorInput"; | import { ColorInput } from "@Component/ColorInput/ColorInput"; | ||||||
| import { Label } from "@Model/Label"; | import { Label } from "@Model/Label"; | ||||||
| import { TogglesInput } from "@Component/TogglesInput/TogglesInput"; | import { TogglesInput } from "@Component/TogglesInput/TogglesInput"; | ||||||
|  | import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||||
| import "./LabelDetails.scss"; | import "./LabelDetails.scss"; | ||||||
| 
 | 
 | ||||||
| @useStatusWithEvent("focusLabelChange", "labelAttrChange", "labelChange") | @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) { |                 if (this.props.status) { | ||||||
|                     this.props.status.model.deleteLabel(label); |                     const status = this.props.status; | ||||||
|                     this.props.status.setLabelObject(); |                     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 { useSetting, IMixinSettingProps } from "@Context/Setting"; | ||||||
| import { Label } from "@Model/Label"; | import { Label } from "@Model/Label"; | ||||||
| import { Message } from "@Component/Message/Message"; | import { Message } from "@Component/Message/Message"; | ||||||
|  | import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||||
| import "./LabelList.scss"; | import "./LabelList.scss"; | ||||||
| 
 | 
 | ||||||
| interface ILabelListProps { | interface ILabelListProps { | ||||||
| @ -47,8 +48,17 @@ class LabelList extends Component<ILabelListProps & IMixinStatusProps & IMixinSe | |||||||
|                 }} |                 }} | ||||||
|                 deleteLabel={(label) => { |                 deleteLabel={(label) => { | ||||||
|                     if (this.props.status) { |                     if (this.props.status) { | ||||||
|                         this.props.status.model.deleteLabel(label); |                         const status = this.props.status; | ||||||
|                         this.props.status.setLabelObject(); |                         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; |                     this.labelInnerClick = true; | ||||||
|                 }} |                 }} | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| import { BackgroundLevel, FontLevel, Theme } from "@Component/Theme/Theme"; | import { BackgroundLevel, FontLevel, Theme } from "@Component/Theme/Theme"; | ||||||
| import { useStatus, IMixinStatusProps } from "../../Context/Status"; | import { useStatus, IMixinStatusProps } from "../../Context/Status"; | ||||||
|  | import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||||
| import { Icon } from "@fluentui/react"; | import { Icon } from "@fluentui/react"; | ||||||
| import { Component, ReactNode } from "react"; | import { Component, ReactNode } from "react"; | ||||||
| import { ObjectID } from "@Model/Renderer"; | import { ObjectID } from "@Model/Renderer"; | ||||||
| @ -54,15 +55,24 @@ class ObjectCommand extends Component<IMixinStatusProps> { | |||||||
| 				<Icon iconName="CubeShape"></Icon> | 				<Icon iconName="CubeShape"></Icon> | ||||||
| 			</div> | 			</div> | ||||||
| 			<div | 			<div | ||||||
| 				className="command-item" | 				className="command-item red" | ||||||
| 				onClick={() => { | 				onClick={() => { | ||||||
| 					if (this.props.status) { | 					if (this.props.status && this.props.status.focusObject.size > 0) { | ||||||
| 						let deleteId: ObjectID[] = []; | 						const status = this.props.status; | ||||||
| 						this.props.status.focusObject.forEach((obj) => { | 						status.popup.showPopup(ConfirmPopup, { | ||||||
| 							deleteId.push(obj); | 							infoI18n: "Popup.Delete.Objects.Confirm", | ||||||
|  | 							titleI18N: "Popup.Action.Objects.Confirm.Title", | ||||||
|  | 							yesI18n: "Popup.Action.Objects.Confirm.Delete", | ||||||
|  | 							red: "yes", | ||||||
|  | 							yes: () => { | ||||||
|  | 								let deleteId: ObjectID[] = []; | ||||||
|  | 								status.focusObject.forEach((obj) => { | ||||||
|  | 									deleteId.push(obj); | ||||||
|  | 								}) | ||||||
|  | 								status.model.deleteObject(deleteId); | ||||||
|  | 								status.setFocusObject(new Set<ObjectID>()); | ||||||
|  | 							} | ||||||
| 						}) | 						}) | ||||||
| 						this.props.status.model.deleteObject(deleteId); |  | ||||||
| 						this.props.status.setFocusObject(new Set<ObjectID>()); |  | ||||||
| 					} | 					} | ||||||
| 				}} | 				}} | ||||||
| 			> | 			> | ||||||
|  | |||||||
| @ -59,6 +59,10 @@ div.object-list-command-bar { | |||||||
|         user-select: none; |         user-select: none; | ||||||
|         cursor: pointer; |         cursor: pointer; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     div.command-item.red:hover { | ||||||
|  |         color: $lt-red; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| div.dark.object-list-command-bar { | div.dark.object-list-command-bar { | ||||||
|  | |||||||
| @ -1,13 +1,13 @@ | |||||||
| import { Component, ReactNode } from "react"; | import { Component, ReactNode } from "react"; | ||||||
| import { AttrInput } from "@Component/AttrInput/AttrInput"; | import { AttrInput } from "@Component/AttrInput/AttrInput"; | ||||||
| import { useStatusWithEvent, IMixinStatusProps, Status } from "@Context/Status"; | import { useStatusWithEvent, IMixinStatusProps, Status } from "@Context/Status"; | ||||||
| import { AllI18nKeys } from "@Component/Localization/Localization"; |  | ||||||
| import { Message } from "@Component/Message/Message"; | import { Message } from "@Component/Message/Message"; | ||||||
| import { Range } from "@Model/Range"; | import { Range } from "@Model/Range"; | ||||||
| import { ObjectID } from "@Model/Renderer"; | import { ObjectID } from "@Model/Renderer"; | ||||||
| import { ColorInput } from "@Component/ColorInput/ColorInput"; | import { ColorInput } from "@Component/ColorInput/ColorInput"; | ||||||
| import { TogglesInput } from "@Component/TogglesInput/TogglesInput"; | import { TogglesInput } from "@Component/TogglesInput/TogglesInput"; | ||||||
| import { LabelPicker } from "@Component/LabelPicker/LabelPicker"; | import { LabelPicker } from "@Component/LabelPicker/LabelPicker"; | ||||||
|  | import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||||
| import "./RangeDetails.scss"; | import "./RangeDetails.scss"; | ||||||
| 
 | 
 | ||||||
| @useStatusWithEvent("rangeAttrChange", "focusObjectChange", "rangeLabelChange") | @useStatusWithEvent("rangeAttrChange", "focusObjectChange", "rangeLabelChange") | ||||||
| @ -53,12 +53,21 @@ class RangeDetails extends Component<IMixinStatusProps> { | |||||||
|             /> |             /> | ||||||
| 
 | 
 | ||||||
|             <TogglesInput |             <TogglesInput | ||||||
| 				keyI18n="Common.Attr.Key.Delete" | 				keyI18n="Common.Attr.Key.Delete" red | ||||||
| 				onIconName="delete" offIconName="delete" | 				onIconName="delete" offIconName="delete" | ||||||
| 				valueChange={() => { | 				valueChange={() => { | ||||||
| 					if (this.props.status) { |                     if (this.props.status) { | ||||||
| 						this.props.status.model.deleteObject([range]); |                         const status = this.props.status; | ||||||
| 						this.props.status.setFocusObject(new Set()); | 						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