SGraphItem.ts 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  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.initData();
  199. this.update();
  200. }
  201. get data(): any | null {
  202. return this._data;
  203. }
  204. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  205. // 函数
  206. /**
  207. * 构造函数
  208. *
  209. * @param parent 指向父对象
  210. */
  211. constructor(parent: SGraphItem | null = null) {
  212. super();
  213. if (parent) {
  214. this.parent = parent;
  215. }
  216. }
  217. /**
  218. * Item 绘制框架
  219. *
  220. * @param painter 绘制对象
  221. * @param rect 绘制区域
  222. */
  223. onPaint(painter: SPainter, rect: SRect): void {
  224. this.onDraw(painter);
  225. for (let item of this.children) {
  226. // 如果 item 不可见
  227. if (!item.visible) {
  228. continue;
  229. }
  230. // item 所占矩阵与要刷新的矩阵相交则刷新,否则不刷
  231. // if (item.boundingRect()--rect){
  232. //
  233. // }
  234. // 保存画布状态
  235. painter.save();
  236. try {
  237. // item 位移到指定位置绘制
  238. painter.translate(item.x, item.y);
  239. painter.scale(item.scale, item.scale);
  240. painter.rotate(item.rotate);
  241. // painter.globalAlpha = item.globalAlpha;
  242. // 如果不进行变形处理,则取消 painter 的变型操作
  243. if (!item.isTransform) {
  244. let matrix = painter.worldTransform;
  245. item._inverseScale = 1.0 / matrix.a;
  246. painter.scale(item._inverseScale, item._inverseScale);
  247. }
  248. // rect 调整 宽度高度取最小值 根据 pos 位移
  249. // 绘制 item
  250. item.onPaint(painter, rect);
  251. } catch (e) {
  252. console.log(e);
  253. }
  254. // 恢复画布状态
  255. painter.restore();
  256. }
  257. }
  258. /**
  259. * Item 绘制操作
  260. *
  261. * @param painter 绘制对象
  262. */
  263. onDraw(painter: SPainter): void {}
  264. /**
  265. * 隐藏对象
  266. */
  267. hide(): void {
  268. this.visible = false;
  269. }
  270. /**
  271. * 显示对象
  272. */
  273. show(): void {
  274. this.visible = true;
  275. }
  276. /**
  277. * 更新 Item
  278. */
  279. update(): void {
  280. if (null != this.scene) {
  281. const view = this.scene.view;
  282. if (null != view) {
  283. view.update();
  284. }
  285. }
  286. }
  287. /**
  288. * Item 对象边界区域
  289. *
  290. * @return 对象边界区域
  291. */
  292. boundingRect(): SRect {
  293. return new SRect(0, 0, 10, 10);
  294. }
  295. /**
  296. * 移动 item 到指定位置
  297. *
  298. * @param x 新位置的 x 坐标
  299. * @param y 新位置的 y 坐标
  300. */
  301. moveTo(x: number, y: number): void {
  302. this.x = x;
  303. this.y = y;
  304. } // moveTo()
  305. /**
  306. * 判断 item 是否包含点 x, y
  307. *
  308. * @param x 横坐标(当前 item)
  309. * @param y 纵坐标(当前 item)
  310. * @return item 是否包含点 x, y
  311. */
  312. contains(x: number, y: number): boolean {
  313. return this.boundingRect().contains(x, y);
  314. }
  315. /**
  316. * 获得 item 的路径节点列表。(该节点被加载到场景中,如果未被加载到场景中,计算会出错)
  317. *
  318. * @return item 的路径节点列表
  319. */
  320. itemPath(): SGraphItem[] {
  321. if (this.parent != null) {
  322. let list = this.parent.itemPath();
  323. list.push(this);
  324. return list;
  325. }
  326. return [this];
  327. }
  328. /**
  329. * 将场景中的 x, y 坐标转换成 item 坐标。(该节点被加载到场景中,如果未被加载到场景中,计算会出错)
  330. *
  331. * @param x 场景中的横坐标
  332. * @param y 场景中的纵坐标
  333. * @return 在 item 中的坐标
  334. */
  335. mapFromScene(x: number, y: number): SPoint {
  336. const m = this.scene2itemMattrix();
  337. return new SPoint(x, y).matrixTransform(m.inversed());
  338. }
  339. /**
  340. * 将 item 中的 x, y 坐标转换成场景坐标。(该节点被加载到场景中,如果未被加载到场景中,计算会出错)
  341. *
  342. * @param x item 中的横坐标
  343. * @param y item 中的纵坐标
  344. * @return 在场景中的坐标
  345. */
  346. mapToScene(x: number, y: number): SPoint {
  347. if (this.parent == null) {
  348. return new SPoint(x, y);
  349. }
  350. const m = this.scene2itemMattrix();
  351. return new SPoint(x, y).matrixTransform(m);
  352. }
  353. /**
  354. * 场景对象到 item 对象的转换矩阵
  355. *
  356. * @return 转换矩阵
  357. */
  358. scene2itemMattrix(): SMatrix {
  359. let m = new SMatrix();
  360. let list = this.itemPath();
  361. for (let item of list) {
  362. m.translate(item.x, item.y);
  363. m.scale(item.scale, item.scale);
  364. m.rotate(item.rotate);
  365. // 如果不进行变形处理,则取消 painter 的变型操作
  366. if (!item.isTransform) {
  367. m.scale(item._inverseScale, item._inverseScale);
  368. }
  369. }
  370. return m;
  371. }
  372. // =================================================================================================================
  373. // 事件
  374. /**
  375. * 鼠标单击事件
  376. *
  377. * @param event 保存事件参数
  378. * @return 是否处理事件
  379. */
  380. onClick(event: SMouseEvent): boolean {
  381. for (let i = this.children.length - 1; i >= 0; i--) {
  382. let item = this.children[i];
  383. if (!this.acceptEvent() || !item.visible) {
  384. continue;
  385. }
  386. let ce = SGraphItem.toChildMouseEvent(item, event);
  387. if (item.contains(ce.x, ce.y) && item.onClick(ce)) {
  388. // 如果点在子项目上且子项目处理了事件
  389. return true;
  390. }
  391. }
  392. return false;
  393. }
  394. /**
  395. * 鼠标双击事件
  396. *
  397. * @param event 保存事件参数
  398. * @return 是否处理事件
  399. */
  400. onDoubleClick(event: SMouseEvent): boolean {
  401. for (let i = this.children.length - 1; i >= 0; i--) {
  402. let item = this.children[i];
  403. if (!this.acceptEvent() || !item.visible) {
  404. continue;
  405. }
  406. let ce = SGraphItem.toChildMouseEvent(item, event);
  407. if (item.contains(ce.x, ce.y) && item.onDoubleClick(ce)) {
  408. // 如果点在子项目上且子项目处理了事件
  409. return true;
  410. }
  411. }
  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. * 初始化数据
  602. */
  603. initData(): void {
  604. // do nothing
  605. }
  606. /**
  607. * 移动 item 后的处理,计算其他信息,将原点置为场景原点
  608. *
  609. * @param x x 坐标
  610. * @param y y 坐标
  611. */
  612. moveToOrigin(x: number, y: number): void {
  613. if (this.children && this.children.length) {
  614. this.children.forEach((it): void => {
  615. it.moveToOrigin(x, y);
  616. });
  617. }
  618. }
  619. // =================================================================================================================
  620. // 私有方法
  621. /**
  622. * 按 ZOrder 排序
  623. *
  624. * @param a 比较元素 1
  625. * @param b 比较元素 2
  626. * @return 2 个元素 zOrder 的差值
  627. */
  628. private static sortItemZOrder(a: SGraphItem, b: SGraphItem): number {
  629. return a.zOrder - b.zOrder;
  630. }
  631. /**
  632. * 鼠标事件转子对象鼠标事件
  633. *
  634. * @param child 子对象
  635. * @param event 事件参数
  636. * @return 子对象鼠标事件
  637. */
  638. private static toChildMouseEvent(
  639. child: SGraphItem,
  640. event: SMouseEvent
  641. ): SMouseEvent {
  642. let ce = new SMouseEvent(event);
  643. ce.matrix.translate(child.x, child.y);
  644. ce.matrix.scale(child.scale, child.scale);
  645. ce.matrix.rotate(0, 0, child.rotate);
  646. if (!child.isTransform) {
  647. ce.matrix.scale(child._inverseScale, child._inverseScale);
  648. }
  649. const mp = new SPoint(event.offsetX, event.offsetY).matrixTransform(
  650. ce.matrix.inversed()
  651. );
  652. ce.x = mp.x;
  653. ce.y = mp.y;
  654. return ce;
  655. }
  656. /**
  657. * 锁定 item
  658. *
  659. * @param item 被锁定的 item
  660. */
  661. protected grabItem(item: SGraphItem): void {
  662. if (this.scene != null) {
  663. this.scene.grabItem = item;
  664. }
  665. }
  666. /**
  667. * 释放被锁定的 item
  668. */
  669. protected releaseItem(): void {
  670. if (this.scene != null) {
  671. this.scene.grabItem = null;
  672. }
  673. }
  674. /**
  675. * 计算点在父节点的位置
  676. *
  677. * @param x X 轴
  678. * @param y Y 轴
  679. * @return 在父节点的位置
  680. */
  681. protected toParentChange(x: number, y: number): SPoint {
  682. const m = new SMatrix();
  683. m.scale(this.scale, this.scale);
  684. if (!this.isTransform) {
  685. m.scale(this._inverseScale, this._inverseScale);
  686. }
  687. m.rotate(this.rotate);
  688. const mp = new SPoint(x, y).matrixTransform(m);
  689. return new SPoint(mp.x, mp.y);
  690. }
  691. /**
  692. * 判断是否处理事件
  693. *
  694. * @return 是否处理事件
  695. */
  696. private acceptEvent(): boolean {
  697. return this.visible && this.enabled;
  698. }
  699. /**
  700. * 点选 item 对象
  701. *
  702. * @param event 事件参数
  703. * @return 是否处理事件
  704. */
  705. private clickSelect(event: SMouseEvent): boolean {
  706. // 如果 Item 不可被选中,或没有按下鼠标左键,则直接返回
  707. if (!this.selectable) {
  708. // || event.buttons != SMouseButton.LeftButton
  709. return false;
  710. }
  711. const scene = this.scene;
  712. if (scene == null) {
  713. return false;
  714. }
  715. // 如果按下 Ctrl 键,只改变当前 item 的选择标志
  716. if (event.ctrlKey) {
  717. scene.selectContainer.toggleItem(this);
  718. } else {
  719. scene.selectContainer.setItem(this);
  720. }
  721. return true;
  722. }
  723. }