import { SMouseEvent, SMatrix } from "@saga-web/base/lib"; import {SPainter, SPoint, SRect} from "@saga-web/draw/lib"; import { SGraphItem } from "./SGraphItem"; import { SGraphView } from "./SGraphView"; import { SGraphSelectContainer } from "./SGraphSelectContainer"; /** * Graphy图形引擎场景类 * * @author 庞利祥(sybotan@126.com) */ export class SGraphScene { /** 展示场景的视图 */ view: SGraphView | null = null; /** 根节点 */ protected root: SGraphItem = new SGraphItem(); /** 当前捕获Item */ grabItem: SGraphItem | null = null; /** 鼠标所在Item */ hoverItem: SGraphItem | null = null; /** 选择器 */ selectContainer: SGraphSelectContainer = new SGraphSelectContainer(); /** * 构造函数 */ constructor() { this.root.scene = this; } // Constructor /** * 添加item对象到场景。 * * @param item 添加的对象 */ addItem(item: SGraphItem): void { item.parent = this.root; } // Functin addItem() /** * 从场景中移除Item。 * * @param item 被移除的对象 */ removeItem(item: SGraphItem): void { item.parent = null; } // Function removeItem() /** * 绘制场景 * * @param painter painter对象 * @param rect 更新绘制区域 */ drawScene(painter: SPainter, rect: SRect): void { this.root.onPaint(painter, rect); } // Function drawScene() /** * 绘制背景 * * @param painter painter对象 * @param rect 更新绘制区域 */ drawBackground(painter: SPainter, rect: SRect) { // DO NOTHING } // Function drawBackground() /** * 绘制前景 * * @param painter painter对象 * @param rect 更新绘制区域 */ drawForeground(painter: SPainter, rect: SRect) { // DO NOTHING } // Function drawForeground() /** * 所有item占用的矩形区域 */ allItemRect(): SRect | null { let rect: SRect | null = null; // 依次取item列中的所有item。将所有item的边界做并焦处理。 for (let item of this.root.children) { if (rect == null) { rect = item.boundingRect().translated(item.pos.x, item.pos.y); } else { rect.union( item.boundingRect().translated(item.pos.x, item.pos.y) ); } } return rect; } // Function allItemRect() /** * 被选中item占用的矩形区域 */ selectedItemRect(): SRect | null { let rect: SRect | null = null; // 依次取item列中的所有item。将所有item的边界做并焦处理。 for (let item of this.root.children) { // 如果item未被选中,则去选择下一个item if (!item.selected) { continue; } if (rect == null) { rect = item.boundingRect().translated(item.pos.x, item.pos.y); } else { rect.union( item.boundingRect().translated(item.pos.x, item.pos.y) ); } } return rect; } // Function selectedItemRect() /** * 获得选中的对象列表 * * @return 选中对象列表 */ selectedItems(): SGraphItem[] { let itemList = Array(); for (let item of this.root.children) { // 如果item未被选中,则去选择下一个item if (item.selected) { itemList.push(item); } } return itemList; } // Function selectedItems() // ================================================================================================================= // 事件 // /** // * 鼠标单击事件 // * // * @param event 保存事件参数 // * @return boolean // */ // onClick(event: SMouseEvent): boolean { // if (this.grabItem != null) { // return this.grabItem.onClick( // SGraphScene.toGrabItemMotionEvent(this.grabItem, event) // ); // } // return this.root.onClick(event); // } // Function onClick() /** * 鼠标双击事件 * * @param event 保存事件参数 * @return boolean */ onDoubleClick(event: SMouseEvent): boolean { if (this.grabItem != null) { return this.grabItem.onDoubleClick( this.toGrabItemMotionEvent(this.grabItem, event) ); } return this.root.onDoubleClick(event); } // Function onDoubleClick() /** * 鼠标按下事件 * * @param event 保存事件参数 * @return boolean */ onMouseDown(event: SMouseEvent): boolean { if (this.grabItem != null) { return this.grabItem.onMouseDown( this.toGrabItemMotionEvent(this.grabItem, event) ); } const flag = this.root.onMouseDown(event); if (!flag && !event.ctrlKey) { this.selectContainer.clear(); } return flag; } // Function onMouseDown() /** * 鼠标移动事件 * * @param event 保存事件参数 * @return boolean */ onMouseMove(event: SMouseEvent): boolean { if (this.grabItem != null) { return this.grabItem.onMouseMove( this.toGrabItemMotionEvent(this.grabItem, event) ); } return this.root.onMouseMove(event); } // Function onMouseMove() /** * 释放鼠标事件 * * @param event 保存事件参数 * @return boolean */ onMouseUp(event: SMouseEvent): boolean { if (this.grabItem != null) { return this.grabItem.onMouseUp( this.toGrabItemMotionEvent(this.grabItem, event) ); } return this.root.onMouseUp(event); } // Function onMouseUp() /** * 上下文菜单事件 * * @param event 事件参数 */ onContextMenu(event: SMouseEvent): boolean { if (this.grabItem != null) { return this.grabItem.onContextMenu( this.toGrabItemMotionEvent(this.grabItem, event) ); } return this.root.onContextMenu(event); } // Function onContextMenu() /** * 按键按下事件 * * @param event 事件参数 */ onKeyDown(event: KeyboardEvent): void { if (this.grabItem != null) { return this.grabItem.onKeyDown(event); } return this.root.onKeyDown(event); } // Function onKeyDown() // /** // * 按键press事件 // * // * @param event 事件参数 // */ // onKeyPress(event: KeyboardEvent): void { // if (this.grabItem != null) { // this.grabItem.onKeyPress(event); // } // } // Function onKeyPress() /** * 按键松开事件 * * @param event 事件参数 */ onKeyUp(event: KeyboardEvent): void { if (this.grabItem != null) { return this.grabItem.onKeyUp(event); } return this.root.onKeyUp(event); } // Function onKeyUp() /** * 转换场景事件坐标到指定Item坐标事件 * * @param item 指定的item对象 * @param event 场景事件 * @return {} */ private toGrabItemMotionEvent( item: SGraphItem, event: SMouseEvent ): SMouseEvent { let se = { ...event }; se.matrix = new SMatrix(); if (this.view) { se.matrix.translate(this.view.origin.x, this.view.origin.y); se.matrix.scale(this.view.scale, this.view.scale); se.matrix.rotate(this.view.rotate); } se.matrix.multiply(item.scene2itemMattrix()); let p = new SPoint(event.offsetX, event.offsetY).matrixTransform( se.matrix.inversed() ); se.x = p.x; se.y = p.y; return se; } // Function toGrabItemMotionEvent() } // Class SGraphScene