SGraphItem.ts 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  1. /*
  2. * *********************************************************************************************************************
  3. *
  4. * !!
  5. * .F88X
  6. * X8888Y
  7. * .}888888N;
  8. * i888888N; .:! .I$WI:
  9. * R888888I .'N88~ i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
  10. * .R888888I .;N8888~ .X8' "8I.!,/8" !%NY8`"8I8~~8>,88I
  11. * +888888N; .8888888Y "&&8Y.}8,
  12. * ./888888N; .R888888Y .'}~ .>}'.`+> i}! "i' +/' .'i~ !11,.:">, .~]! .i}i
  13. * ~888888%: .I888888l .]88~`1/iY88Ii+1'.R$8$8]"888888888> Y8$ W8E X8E W8888'188Il}Y88$*
  14. * 18888888 E8888881 .]W%8$`R8X'&8%++N8i,8N%N8+l8%` .}8N:.R$RE%N88N%N$K$R 188,FE$8%~Y88I
  15. * .E888888I .i8888888' .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
  16. * 8888888I .,N888888~ ~88i"8W,!N8*.I88.}888%F,i$88"F88" 888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
  17. * i888888N' I888Y ]88;/EX*IFKFK88X K8R .l8W 88Y ~88}'88E&%8W.X8N``]88!.$8K .:W8I
  18. * .i888888N; I8Y .&8$ .X88! i881.:%888>I88 ;88] +88+.';;;;:.Y88X 18N.,88l .+88/
  19. * .:R888888I
  20. * .&888888I Copyright (c) 2009-2020. 博锐尚格科技股份有限公司
  21. * ~8888'
  22. * .!88~ All rights reserved.
  23. *
  24. * *********************************************************************************************************************
  25. */
  26. import { SMouseButton, SMouseEvent, SObject, SMatrix } from "@persagy-web/base";
  27. import { SPainter, SPoint, SRect } from "@persagy-web/draw";
  28. import { SGraphScene } from "./SGraphScene";
  29. import { SPath } from "@persagy-web/draw/lib";
  30. /**
  31. * Graph 图形引擎 Item 类
  32. *
  33. * @author 庞利祥 <sybotan@126.com>
  34. */
  35. export class SGraphItem extends SObject {
  36. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  37. // 属性
  38. /** 场景对象 */
  39. private _scene: SGraphScene | null = null;
  40. get scene(): SGraphScene | null {
  41. if (null != this._parent) {
  42. return this._parent.scene;
  43. } else {
  44. return this._scene;
  45. }
  46. }
  47. set scene(v: SGraphScene | null) {
  48. this._scene = v;
  49. this.update();
  50. }
  51. /** parent 属性存值函数 */
  52. private _parent: SGraphItem | null = null;
  53. get parent(): SGraphItem | null {
  54. return this._parent;
  55. }
  56. set parent(v: SGraphItem | null) {
  57. // 如果 parent 未变更
  58. if (this.parent == v) {
  59. return;
  60. }
  61. // 如果原 parent 不为空
  62. if (this._parent != null) {
  63. // 将节点从原 parent 节点中摘除
  64. let i = this._parent.children.indexOf(this);
  65. this._parent.children.splice(i, 1);
  66. }
  67. this._parent = v;
  68. this.update();
  69. // 如果新 parent 不为空
  70. if (this._parent != null) {
  71. // 将节点加入到新 parent 节点中
  72. this._parent.children.push(this);
  73. this._parent.children.sort(SGraphItem.sortItemZOrder);
  74. }
  75. }
  76. /** 子节点 */
  77. children: SGraphItem[] = [];
  78. /** Z 轴顺序 */
  79. private _zOrder: number = 0;
  80. get zOrder(): number {
  81. return this._zOrder;
  82. }
  83. set zOrder(v: number) {
  84. this._zOrder = v;
  85. if (this._parent != null) {
  86. this._parent.children.sort(SGraphItem.sortItemZOrder);
  87. }
  88. this.update();
  89. }
  90. /** 位置 */
  91. pos: SPoint = new SPoint(0, 0);
  92. /** X 轴坐标 */
  93. get x(): number {
  94. return this.pos.x;
  95. }
  96. set x(v: number) {
  97. if (this.pos.x == v) {
  98. return;
  99. }
  100. let old = this.pos.x;
  101. this.pos.x = v;
  102. this.update();
  103. }
  104. /** Y 轴坐标 */
  105. get y(): number {
  106. return this.pos.y;
  107. }
  108. set y(v: number) {
  109. if (this.pos.y == v) {
  110. return;
  111. }
  112. let old = this.pos.y;
  113. this.pos.y = v;
  114. this.update();
  115. }
  116. /** 缩放比例 */
  117. scale: number = 1;
  118. /** 放缩反比例 */
  119. private _inverseScale: number = 1;
  120. get inverseScale(): number {
  121. return this._inverseScale;
  122. }
  123. /** 旋转角度 */
  124. _rotate: number = 0;
  125. get rotate(): number {
  126. return this._rotate;
  127. }
  128. set rotate(v: number) {
  129. this._rotate = v;
  130. this.update();
  131. }
  132. /** 是否可见 */
  133. private _visible: boolean = true;
  134. get visible(): boolean {
  135. return this._visible;
  136. }
  137. set visible(v: boolean) {
  138. this._visible = v;
  139. this.update();
  140. }
  141. /** 透明度 */
  142. private _globalAlpha = 1;
  143. get globalAlpha(): number {
  144. return this._globalAlpha;
  145. } // Get number
  146. set globalAlpha(v: number) {
  147. this._globalAlpha = v;
  148. this.update();
  149. } // Set number
  150. /** 是否可以移动 */
  151. moveable: boolean = false;
  152. /** 是否正在移动 */
  153. protected _isMoving = false;
  154. /** 是否可用 */
  155. protected _enabled: boolean = true;
  156. get enabled(): boolean {
  157. return this._enabled;
  158. }
  159. set enabled(value: boolean) {
  160. // 如果选择状态未变更
  161. if (this.enabled == value) {
  162. return;
  163. }
  164. this._enabled = value;
  165. this.update();
  166. }
  167. /** 是否可被选中 */
  168. selectable = false;
  169. /** 是否被选中 */
  170. protected _selected = false;
  171. get selected(): boolean {
  172. return this._selected && this.selectable && this.enabled;
  173. }
  174. set selected(value: boolean) {
  175. // 如果选择状态未变更
  176. if (this.selected == value) {
  177. return;
  178. }
  179. this._selected = value;
  180. this.update();
  181. }
  182. /** 是否可修改大小 */
  183. _resizeable: boolean = true;
  184. /** 选中时是否显示选择器 */
  185. showSelect: boolean = true;
  186. /** 是否进行变形 */
  187. isTransform = true;
  188. /** 鼠标按下时位置 */
  189. protected _mouseDownPos = new SPoint();
  190. /** 鼠标样式 */
  191. cursor: string = "default";
  192. /** 保存上一次的 grabItem */
  193. private _lastGrab: SGraphItem | null = null;
  194. /** 外层自定义数据 */
  195. private _data: any | null = null;
  196. set data(d: any) {
  197. this._data = d;
  198. this.update();
  199. }
  200. get data(): any | null {
  201. return this._data;
  202. }
  203. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  204. // 函数
  205. /**
  206. * 构造函数
  207. *
  208. * @param parent 指向父对象
  209. */
  210. constructor(parent: SGraphItem | null = null) {
  211. super();
  212. if (parent) {
  213. this.parent = parent;
  214. }
  215. }
  216. /**
  217. * Item 绘制框架
  218. *
  219. * @param painter 绘制对象
  220. * @param rect 绘制区域
  221. */
  222. onPaint(painter: SPainter, rect: SRect): void {
  223. this.onDraw(painter);
  224. for (let item of this.children) {
  225. // 如果 item 不可见
  226. if (!item.visible) {
  227. continue;
  228. }
  229. // item 所占矩阵与要刷新的矩阵相交则刷新,否则不刷
  230. // if (item.boundingRect()--rect){
  231. //
  232. // }
  233. // 保存画布状态
  234. painter.save();
  235. try {
  236. // item 位移到指定位置绘制
  237. painter.translate(item.x, item.y);
  238. painter.scale(item.scale, item.scale);
  239. painter.rotate(item.rotate);
  240. // painter.globalAlpha = item.globalAlpha;
  241. // 如果不进行变形处理,则取消 painter 的变型操作
  242. if (!item.isTransform) {
  243. let matrix = painter.worldTransform;
  244. item._inverseScale = 1.0 / matrix.a;
  245. painter.scale(item._inverseScale, item._inverseScale);
  246. }
  247. // rect 调整 宽度高度取最小值 根据 pos 位移
  248. // 绘制 item
  249. item.onPaint(painter, rect);
  250. } catch (e) {
  251. console.log(e);
  252. }
  253. // 恢复画布状态
  254. painter.restore();
  255. }
  256. }
  257. /**
  258. * Item 绘制操作
  259. *
  260. * @param painter 绘制对象
  261. */
  262. onDraw(painter: SPainter): void {}
  263. /**
  264. * 隐藏对象
  265. */
  266. hide(): void {
  267. this.visible = false;
  268. }
  269. /**
  270. * 显示对象
  271. */
  272. show(): void {
  273. this.visible = true;
  274. }
  275. /**
  276. * 更新 Item
  277. */
  278. update(): void {
  279. if (null != this.scene) {
  280. const view = this.scene.view;
  281. if (null != view) {
  282. view.update();
  283. }
  284. }
  285. }
  286. /**
  287. * Item 对象边界区域
  288. *
  289. * @return 对象边界区域
  290. */
  291. boundingRect(): SRect {
  292. return new SRect(0, 0, 10, 10);
  293. }
  294. /**
  295. * 移动 item 到指定位置
  296. *
  297. * @param x 新位置的 x 坐标
  298. * @param y 新位置的 y 坐标
  299. */
  300. moveTo(x: number, y: number): void {
  301. this.x = x;
  302. this.y = y;
  303. } // moveTo()
  304. /**
  305. * 判断 item 是否包含点 x, y
  306. *
  307. * @param x 横坐标(当前 item)
  308. * @param y 纵坐标(当前 item)
  309. * @return item 是否包含点 x, y
  310. */
  311. contains(x: number, y: number): boolean {
  312. return this.boundingRect().contains(x, y);
  313. }
  314. /**
  315. * 获得 item 的路径节点列表。(该节点被加载到场景中,如果未被加载到场景中,计算会出错)
  316. *
  317. * @return item 的路径节点列表
  318. */
  319. itemPath(): SGraphItem[] {
  320. if (this.parent != null) {
  321. let list = this.parent.itemPath();
  322. list.push(this);
  323. return list;
  324. }
  325. return [this];
  326. }
  327. /**
  328. * 将场景中的 x, y 坐标转换成 item 坐标。(该节点被加载到场景中,如果未被加载到场景中,计算会出错)
  329. *
  330. * @param x 场景中的横坐标
  331. * @param y 场景中的纵坐标
  332. * @return 在 item 中的坐标
  333. */
  334. mapFromScene(x: number, y: number): SPoint {
  335. const m = this.scene2itemMattrix();
  336. return new SPoint(x, y).matrixTransform(m.inversed());
  337. }
  338. /**
  339. * 将 item 中的 x, y 坐标转换成场景坐标。(该节点被加载到场景中,如果未被加载到场景中,计算会出错)
  340. *
  341. * @param x item 中的横坐标
  342. * @param y item 中的纵坐标
  343. * @return 在场景中的坐标
  344. */
  345. mapToScene(x: number, y: number): SPoint {
  346. if (this.parent == null) {
  347. return new SPoint(x, y);
  348. }
  349. const m = this.scene2itemMattrix();
  350. return new SPoint(x, y).matrixTransform(m);
  351. }
  352. /**
  353. * 场景对象到 item 对象的转换矩阵
  354. *
  355. * @return 转换矩阵
  356. */
  357. scene2itemMattrix(): SMatrix {
  358. let m = new SMatrix();
  359. let list = this.itemPath();
  360. for (let item of list) {
  361. m.translate(item.x, item.y);
  362. m.scale(item.scale, item.scale);
  363. m.rotate(item.rotate);
  364. // 如果不进行变形处理,则取消 painter 的变型操作
  365. if (!item.isTransform) {
  366. m.scale(item._inverseScale, item._inverseScale);
  367. }
  368. }
  369. return m;
  370. }
  371. // =================================================================================================================
  372. // 事件
  373. /**
  374. * 鼠标单击事件
  375. *
  376. * @param event 保存事件参数
  377. * @return 是否处理事件
  378. */
  379. onClick(event: SMouseEvent): boolean {
  380. for (let i = this.children.length - 1; i >= 0; i--) {
  381. let item = this.children[i];
  382. if (!this.acceptEvent() || !item.visible) {
  383. continue;
  384. }
  385. let ce = SGraphItem.toChildMouseEvent(item, event);
  386. if (item.contains(ce.x, ce.y) && item.onClick(ce)) {
  387. // 如果点在子项目上且子项目处理了事件
  388. return true;
  389. }
  390. }
  391. return false;
  392. }
  393. /**
  394. * 鼠标双击事件
  395. *
  396. * @param event 保存事件参数
  397. * @return 是否处理事件
  398. */
  399. onDoubleClick(event: SMouseEvent): boolean {
  400. for (let i = this.children.length - 1; i >= 0; i--) {
  401. let item = this.children[i];
  402. if (!this.acceptEvent() || !item.visible) {
  403. continue;
  404. }
  405. let ce = SGraphItem.toChildMouseEvent(item, event);
  406. if (item.contains(ce.x, ce.y) && item.onDoubleClick(ce)) {
  407. // 如果点在子项目上且子项目处理了事件
  408. return true;
  409. }
  410. }
  411. this.$emit("onDoubleClick", event);
  412. return false;
  413. }
  414. /**
  415. * 鼠标按下事件
  416. *
  417. * @param event 保存事件参数
  418. * @return 是否处理事件
  419. */
  420. onMouseDown(event: SMouseEvent): boolean {
  421. for (let i = this.children.length - 1; i >= 0; i--) {
  422. try {
  423. let item = this.children[i];
  424. if (!this.acceptEvent() || !item.visible) {
  425. continue;
  426. }
  427. let ce = SGraphItem.toChildMouseEvent(item, event);
  428. if (item.contains(ce.x, ce.y) && item.onMouseDown(ce)) {
  429. // 如果点在子项目上且子项目处理了事件
  430. return true;
  431. }
  432. } catch (e) {
  433. console.log(e);
  434. }
  435. }
  436. this.$emit("onMouseDown", event);
  437. // 移动
  438. if (this.moveable) {
  439. this._mouseDownPos = new SPoint(event.x, event.y);
  440. this._isMoving = true;
  441. if (this.scene) {
  442. this._lastGrab = this.scene.grabItem;
  443. }
  444. this.grabItem(this);
  445. return true;
  446. }
  447. return false;
  448. }
  449. /**
  450. * 鼠标移动事件
  451. *
  452. * @param event 保存事件参数
  453. * @return 是否处理事件
  454. */
  455. onMouseMove(event: SMouseEvent): boolean {
  456. for (let i = this.children.length - 1; i >= 0; i--) {
  457. let item = this.children[i];
  458. if (!this.acceptEvent() || !item.visible) {
  459. continue;
  460. }
  461. let ce = SGraphItem.toChildMouseEvent(item, event);
  462. if (item.contains(ce.x, ce.y) && item.onMouseMove(ce)) {
  463. // 如果点在子项目上且子项目处理了事件
  464. return true;
  465. }
  466. }
  467. this.$emit("onMouseMove", event);
  468. if (this.scene && this.scene.view) {
  469. this.scene.view.cursor = this.cursor;
  470. }
  471. if (
  472. event.buttons & SMouseButton.LeftButton &&
  473. this.moveable &&
  474. this._isMoving
  475. ) {
  476. let old = new SPoint(this.pos.x, this.pos.y);
  477. const mp = this.toParentChange(
  478. event.x - this._mouseDownPos.x,
  479. event.y - this._mouseDownPos.y
  480. );
  481. this.moveTo(this.pos.x + mp.x, this.pos.y + mp.y);
  482. this.$emit("onMove", old, this.pos);
  483. }
  484. // 处理 hover
  485. const scene = this.scene;
  486. if (null != scene) {
  487. if (scene.hoverItem == null || scene.hoverItem !== this) {
  488. if (scene.hoverItem != null) {
  489. scene.hoverItem.onMouseLeave(event);
  490. }
  491. this.onMouseEnter(event);
  492. scene.hoverItem = this;
  493. }
  494. }
  495. return true;
  496. }
  497. /**
  498. * 释放鼠标事件
  499. *
  500. * @param event 保存事件参数
  501. * @return 是否处理事件
  502. */
  503. onMouseUp(event: SMouseEvent): boolean {
  504. for (let i = this.children.length - 1; i >= 0; i--) {
  505. let item = this.children[i];
  506. if (!this.acceptEvent() || !item.visible) {
  507. continue;
  508. }
  509. let ce = SGraphItem.toChildMouseEvent(item, event);
  510. if (item.contains(ce.x, ce.y) && item.onMouseUp(ce)) {
  511. // 如果点在子项目上且子项目处理了事件
  512. return true;
  513. }
  514. }
  515. // 选择
  516. let select = false;
  517. // 是否可选中
  518. if (this.selectable) {
  519. select = this.clickSelect(event);
  520. }
  521. this.$emit("onMouseUp", event);
  522. this._isMoving = false;
  523. this.releaseItem();
  524. if (this.scene) {
  525. this.scene.grabItem = this._lastGrab;
  526. }
  527. return select;
  528. }
  529. /**
  530. * 鼠标进入事件
  531. *
  532. * @param event 保存事件参数
  533. * @return 是否处理事件
  534. */
  535. onMouseEnter(event: SMouseEvent): boolean {
  536. this.$emit("onMouseEnter", event);
  537. return false;
  538. }
  539. /**
  540. * 鼠标离开事件
  541. *
  542. * @param event 保存事件参数
  543. * @return 是否处理事件
  544. */
  545. onMouseLeave(event: SMouseEvent): boolean {
  546. this.$emit("onMouseLeave", event);
  547. return false;
  548. }
  549. /**
  550. * 上下文菜单事件
  551. *
  552. * @param event 事件参数
  553. * @return 是否处理事件
  554. */
  555. onContextMenu(event: SMouseEvent): boolean {
  556. for (let i = this.children.length - 1; i >= 0; i--) {
  557. let item = this.children[i];
  558. if (!this.acceptEvent() || !item.visible) {
  559. continue;
  560. }
  561. let ce = SGraphItem.toChildMouseEvent(item, event);
  562. if (item.contains(ce.x, ce.y) && item.onContextMenu(ce)) {
  563. // 如果点在子项目上且子项目处理了事件
  564. return true;
  565. }
  566. }
  567. this.$emit("onContextMenu", event);
  568. return false;
  569. }
  570. /**
  571. * 按键按下事件
  572. *
  573. * @param event 事件参数
  574. */
  575. onKeyDown(event: KeyboardEvent): void {}
  576. /**
  577. * 按键 press 事件
  578. *
  579. * @param event 事件参数
  580. */
  581. onKeyPress(event: KeyboardEvent): void {}
  582. /**
  583. * 按键松开事件
  584. *
  585. * @param event 事件参数
  586. */
  587. onKeyUp(event: KeyboardEvent): void {}
  588. /**
  589. * 取消操作 item 事件
  590. */
  591. cancelOperate(): void {}
  592. /**
  593. * 返回 item 对应的数据对象
  594. *
  595. * @return item 数据
  596. */
  597. toData(): any | null {
  598. return null;
  599. }
  600. /**
  601. * 移动 item 后的处理,计算其他信息,将原点置为场景原点
  602. *
  603. * @param x x 坐标
  604. * @param y y 坐标
  605. */
  606. moveToOrigin(x: number, y: number): void {
  607. if (this.children && this.children.length) {
  608. this.children.forEach((it): void => {
  609. it.moveToOrigin(x, y);
  610. });
  611. }
  612. }
  613. // =================================================================================================================
  614. // 私有方法
  615. /**
  616. * 按 ZOrder 排序
  617. *
  618. * @param a 比较元素 1
  619. * @param b 比较元素 2
  620. * @return 2 个元素 zOrder 的差值
  621. */
  622. private static sortItemZOrder(a: SGraphItem, b: SGraphItem): number {
  623. return a.zOrder - b.zOrder;
  624. }
  625. /**
  626. * 鼠标事件转子对象鼠标事件
  627. *
  628. * @param child 子对象
  629. * @param event 事件参数
  630. * @return 子对象鼠标事件
  631. */
  632. private static toChildMouseEvent(
  633. child: SGraphItem,
  634. event: SMouseEvent
  635. ): SMouseEvent {
  636. let ce = new SMouseEvent(event);
  637. ce.matrix.translate(child.x, child.y);
  638. ce.matrix.scale(child.scale, child.scale);
  639. ce.matrix.rotate(0, 0, child.rotate);
  640. if (!child.isTransform) {
  641. ce.matrix.scale(child._inverseScale, child._inverseScale);
  642. }
  643. const mp = new SPoint(event.offsetX, event.offsetY).matrixTransform(
  644. ce.matrix.inversed()
  645. );
  646. ce.x = mp.x;
  647. ce.y = mp.y;
  648. return ce;
  649. }
  650. /**
  651. * 锁定 item
  652. *
  653. * @param item 被锁定的 item
  654. */
  655. protected grabItem(item: SGraphItem): void {
  656. if (this.scene != null) {
  657. this.scene.grabItem = item;
  658. }
  659. }
  660. /**
  661. * 释放被锁定的 item
  662. */
  663. protected releaseItem(): void {
  664. if (this.scene != null) {
  665. this.scene.grabItem = null;
  666. }
  667. }
  668. /**
  669. * 计算点在父节点的位置
  670. *
  671. * @param x X 轴
  672. * @param y Y 轴
  673. * @return 在父节点的位置
  674. */
  675. protected toParentChange(x: number, y: number): SPoint {
  676. const m = new SMatrix();
  677. m.scale(this.scale, this.scale);
  678. if (!this.isTransform) {
  679. m.scale(this._inverseScale, this._inverseScale);
  680. }
  681. m.rotate(this.rotate);
  682. const mp = new SPoint(x, y).matrixTransform(m);
  683. return new SPoint(mp.x, mp.y);
  684. }
  685. /**
  686. * 判断是否处理事件
  687. *
  688. * @return 是否处理事件
  689. */
  690. private acceptEvent(): boolean {
  691. return this.visible && this.enabled;
  692. }
  693. /**
  694. * 点选 item 对象
  695. *
  696. * @param event 事件参数
  697. * @return 是否处理事件
  698. */
  699. private clickSelect(event: SMouseEvent): boolean {
  700. // 如果 Item 不可被选中,或没有按下鼠标左键,则直接返回
  701. if (!this.selectable) {
  702. // || event.buttons != SMouseButton.LeftButton
  703. return false;
  704. }
  705. const scene = this.scene;
  706. if (scene == null) {
  707. return false;
  708. }
  709. // 如果按下 Ctrl 键,只改变当前 item 的选择标志
  710. if (event.ctrlKey) {
  711. scene.selectContainer.toggleItem(this);
  712. } else {
  713. scene.selectContainer.setItem(this);
  714. }
  715. return true;
  716. }
  717. }