PageRenderTime 57ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/cwxeditor_src/cwx/editor/gui/dwt/motionview.d

https://bitbucket.org/k4nagatsuki/cwxeditor
D | 1529 lines | 1496 code | 29 blank | 4 comment | 273 complexity | b9e078eb5508c1bd1ef034d34d53233e MD5 | raw file
Possible License(s): LGPL-2.1
  1. module cwx.editor.gui.dwt.motionview;
  2. import cwx.card;
  3. import cwx.motion;
  4. import cwx.types;
  5. import cwx.summary;
  6. import cwx.utils;
  7. import cwx.xml;
  8. import cwx.skin;
  9. import cwx.event;
  10. import cwx.path;
  11. import cwx.menu;
  12. import cwx.types;
  13. import cwx.system;
  14. import cwx.editor.gui.dwt.dprops;
  15. import cwx.editor.gui.dwt.dskin;
  16. import cwx.editor.gui.dwt.dutils;
  17. import cwx.editor.gui.dwt.commons;
  18. import cwx.editor.gui.dwt.customtable;
  19. import cwx.editor.gui.dwt.centerlayout;
  20. import cwx.editor.gui.dwt.effectcarddialog;
  21. import cwx.editor.gui.dwt.xmlbytestransfer;
  22. import cwx.editor.gui.dwt.undo;
  23. import cwx.editor.gui.dwt.eventwindow;
  24. import cwx.editor.gui.dwt.dmenu;
  25. import cwx.editor.gui.dwt.incsearch;
  26. import std.string;
  27. import std.datetime;
  28. import std.conv;
  29. import org.eclipse.swt.all;
  30. import java.lang.all;
  31. public:
  32. class MotionView : Composite {
  33. public:
  34. /// ?????????????????????
  35. void delegate()[] warningEvent;
  36. /// ??????????????
  37. void delegate()[] modEvent;
  38. private:
  39. static class MVUndo : Undo {
  40. protected MotionView _v = null;
  41. protected Commons comm;
  42. private int _selected = -1, _selectedB = -1;
  43. this (MotionView v, Commons comm) { mixin(S_TRACE);
  44. _v = v;
  45. this.comm = comm;
  46. save(v);
  47. }
  48. private void save(MotionView v) { mixin(S_TRACE);
  49. if (!v || v.isDisposed()) return;
  50. _selected = v._motions.getSelectionIndex();
  51. }
  52. abstract override void undo();
  53. abstract override void redo();
  54. abstract override void dispose();
  55. protected void udb(MotionView v) { mixin(S_TRACE);
  56. _selectedB = _selected;
  57. save(v);
  58. }
  59. protected void uda(MotionView v) { mixin(S_TRACE);
  60. scope (exit) comm.refreshToolBar();
  61. if (!v || v.isDisposed()) return;
  62. v._motions.select(_selectedB);
  63. v._motions.showSelection();
  64. v.refreshSels(true);
  65. }
  66. protected MotionView view() { mixin(S_TRACE);
  67. return _v;
  68. }
  69. }
  70. static class UndoEdit : MVUndo {
  71. private Motion _old;
  72. private int _index;
  73. this (MotionView v, Commons comm, int index) { mixin(S_TRACE);
  74. super (v, comm);
  75. _old = v.motion(index).dup;
  76. _old.setUseCounter(comm.summary.useCounter.sub);
  77. _index = index;
  78. }
  79. private void impl() { mixin(S_TRACE);
  80. auto v = view();
  81. udb(v);
  82. scope (exit) uda(v);
  83. if (!v || v.isDisposed()) return;
  84. auto old = _old;
  85. _old.removeUseCounter();
  86. _old = v.motion(_index).dup;
  87. _old.setUseCounter(comm.summary.useCounter.sub);
  88. auto m = v.motion(_index);
  89. v.motion(_index, old, false);
  90. }
  91. override void undo() {impl();}
  92. override void redo() {impl();}
  93. override void dispose() { mixin(S_TRACE);
  94. _old.removeUseCounter();
  95. }
  96. }
  97. void storeEdit(int index) { mixin(S_TRACE);
  98. _undo ~= new UndoEdit(this, _comm, index);
  99. }
  100. static class UndoSwap : MVUndo {
  101. private int _index1, _index2;
  102. this (MotionView v, Commons comm, int index1, int index2) { mixin(S_TRACE);
  103. super (v, comm);
  104. _index1 = index1;
  105. _index2 = index2;
  106. }
  107. private void impl() { mixin(S_TRACE);
  108. auto v = view();
  109. udb(v);
  110. scope (exit) uda(v);
  111. if (!v || v.isDisposed()) return;
  112. v.swap(_index1, _index2, false);
  113. }
  114. override void undo() {impl();}
  115. override void redo() {impl();}
  116. override void dispose() {}
  117. }
  118. void storeSwap(int index1, int index2) { mixin(S_TRACE);
  119. _undo ~= new UndoSwap(this, _comm, index1, index2);
  120. }
  121. static class UndoMove : MVUndo {
  122. private int _from, _to;
  123. this (MotionView v, Commons comm, int from, int to) { mixin(S_TRACE);
  124. super (v, comm);
  125. _from = from;
  126. _to = to;
  127. if (_from < _to) _to--;
  128. }
  129. private void impl() { mixin(S_TRACE);
  130. auto v = view();
  131. udb(v);
  132. scope (exit) uda(v);
  133. if (!v || v.isDisposed()) return;
  134. int from = _from;
  135. int to = _to;
  136. auto m = v.motion(to);
  137. v.removeMotion(to, false, false, false);
  138. v.appendMotion(m, from, true, true, false);
  139. std.algorithm.swap(_from, _to);
  140. }
  141. override void undo() {impl();}
  142. override void redo() {impl();}
  143. override void dispose() {}
  144. }
  145. void storeMove(int from, int to) { mixin(S_TRACE);
  146. _undo ~= new UndoMove(this, _comm, from, to);
  147. }
  148. static class UndoInsertDelete : MVUndo {
  149. private bool _insert;
  150. private int _index;
  151. private Motion _m = null;
  152. this (MotionView v, Commons comm, int index, bool insert) { mixin(S_TRACE);
  153. super (v, comm);
  154. _insert = insert;
  155. _index = index;
  156. if (!insert) { mixin(S_TRACE);
  157. initUndoDelete(v);
  158. }
  159. }
  160. private void initUndoDelete(MotionView v) { mixin(S_TRACE);
  161. if (!v || v.isDisposed()) return;
  162. _m = v.motion(_index).dup;
  163. _m.setUseCounter(comm.summary.useCounter.sub);
  164. }
  165. private void undoInsert() { mixin(S_TRACE);
  166. auto v = view();
  167. udb(v);
  168. scope (exit) uda(v);
  169. _insert = false;
  170. initUndoDelete(v);
  171. if (!v || v.isDisposed()) return;
  172. v.removeMotion(_index, true, true, false);
  173. }
  174. void undoDelete() { mixin(S_TRACE);
  175. auto v = view();
  176. udb(v);
  177. scope (exit) uda(v);
  178. if (!v || v.isDisposed()) return;
  179. auto m = _m;
  180. _m.removeUseCounter();
  181. _m = null;
  182. _insert = true;
  183. v.appendMotion(m, _index, true, true, false);
  184. }
  185. override void undo() { mixin(S_TRACE);
  186. if (_insert) { mixin(S_TRACE);
  187. undoInsert();
  188. } else { mixin(S_TRACE);
  189. undoDelete();
  190. }
  191. }
  192. override void redo() { mixin(S_TRACE);
  193. undo();
  194. }
  195. override void dispose() { mixin(S_TRACE);
  196. if (_m) { mixin(S_TRACE);
  197. _m.removeUseCounter();
  198. }
  199. }
  200. }
  201. void storeInsert(int index) { mixin(S_TRACE);
  202. _undo ~= new UndoInsertDelete(this, _comm, index, true);
  203. }
  204. void storeDelete(int index) { mixin(S_TRACE);
  205. _undo ~= new UndoInsertDelete(this, _comm, index, false);
  206. }
  207. string _id;
  208. int _readOnly = 0;
  209. Commons _comm;
  210. Props _prop;
  211. Summary _summ;
  212. UndoManager _undo;
  213. KeyDownFilter _kdFilter;
  214. Table _motions;
  215. Combo _beasts;
  216. BeastCard _selectedBeast = null;
  217. BeastCard[int] _beastTbl;
  218. IncSearch _beastIncSearch;
  219. void beastIncSearch() { mixin(S_TRACE);
  220. .forceFocus(_beasts, true);
  221. _beastIncSearch.startIncSearch();
  222. }
  223. Canvas _beastImg;
  224. Spinner _maxNest;
  225. string[MType] _descs;
  226. Table _motionElm;
  227. Button _dmgTyp[DamageType];
  228. Scale _abiVal;
  229. Spinner _rndRound;
  230. Spinner _abiRound;
  231. Spinner _valValue;
  232. Image[TypeInfo] _imgMsns;
  233. Image[Element] _imgElm;
  234. Skin _summSkin;
  235. @property
  236. Skin summSkin() { mixin(S_TRACE);
  237. return _summSkin ? _summSkin : _comm.skin;
  238. }
  239. HashSet!BeastEventWindow _beWin;
  240. BeastEventWindow openBeastEventWin(BeastCard beast) { mixin(S_TRACE);
  241. if (0 != beast.linkId) { mixin(S_TRACE);
  242. auto b = _summ.beast(beast.linkId);
  243. if (!b) return null;
  244. return _comm.openUseEvents(_prop, _summ, b, true);
  245. }
  246. auto w = _comm.openUseEvents(_prop, _summ, beast, true);
  247. if (_beWin.contains(w)) return w;
  248. w.shell.addDisposeListener(new CloseRemover!(BeastEventWindow)(_beWin, w));
  249. _beWin.add(w);
  250. return w;
  251. }
  252. void editBeastUseEvent() { mixin(S_TRACE);
  253. auto m = selection;
  254. if (!m || !m.detail.use(MArg.BEAST)) return;
  255. auto b = m.beast;
  256. if (!b) return;
  257. openBeastEventWin(b);
  258. }
  259. bool canEditBeast() { mixin(S_TRACE);
  260. auto m = selection;
  261. if (!m || !m.beast) return false;
  262. if (0 != m.beast.linkId && !_summ.beast(m.beast.linkId)) return false;
  263. return true;
  264. }
  265. Motion motion(int index) { mixin(S_TRACE);
  266. return cast(Motion) _motions.getItem(index).getData();
  267. }
  268. void motion(int index, Motion m, bool store) { mixin(S_TRACE);
  269. if (store) storeEdit(index);
  270. auto itm = _motions.getItem(index);
  271. auto o = cast(Motion) itm.getData();
  272. assert (o);
  273. if (o.beast) { mixin(S_TRACE);
  274. _comm.delBeast.call(o.beast);
  275. }
  276. itm.setData(m);
  277. if (index == _motions.getSelectionIndex()) { mixin(S_TRACE);
  278. refreshSels();
  279. }
  280. foreach (dlg; modEvent) dlg();
  281. foreach (dlg; warningEvent) dlg();
  282. }
  283. @property
  284. Motion selection() { mixin(S_TRACE);
  285. int i = _motions.getSelectionIndex();
  286. if (i >= 0) { mixin(S_TRACE);
  287. return motion(i);
  288. }
  289. return null;
  290. }
  291. class DamageTypeListener : SelectionAdapter {
  292. override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  293. auto m = selection;
  294. if (!m) return;
  295. auto val = getRadioValue!(DamageType)(_dmgTyp);
  296. if (m.damageType != val) { mixin(S_TRACE);
  297. storeEdit(_motions.getSelectionIndex());
  298. m.damageType = val;
  299. foreach (dlg; modEvent) dlg();
  300. }
  301. }
  302. }
  303. class AbiValListener : SelectionAdapter {
  304. override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  305. auto m = selection;
  306. if (!m) return;
  307. auto val = _abiVal.getSelection() - Motion.aValue_max;
  308. if (m.aValue != val) { mixin(S_TRACE);
  309. storeEdit(_motions.getSelectionIndex());
  310. m.aValue = val;
  311. foreach (dlg; modEvent) dlg();
  312. }
  313. }
  314. }
  315. void roundEnter(int value) { mixin(S_TRACE);
  316. auto m = selection;
  317. if (!m) return;
  318. if (m.round != value) { mixin(S_TRACE);
  319. storeEdit(_motions.getSelectionIndex());
  320. m.round = value;
  321. foreach (dlg; modEvent) dlg();
  322. }
  323. }
  324. int roundCancel(int oldVal) { mixin(S_TRACE);
  325. roundEnter(oldVal);
  326. return oldVal;
  327. }
  328. void valEnter(int value) { mixin(S_TRACE);
  329. auto m = selection;
  330. if (!m) return;
  331. if (m.uValue != value) { mixin(S_TRACE);
  332. storeEdit(_motions.getSelectionIndex());
  333. m.uValue = value;
  334. foreach (dlg; modEvent) dlg();
  335. }
  336. }
  337. int valCancel(int oldVal) { mixin(S_TRACE);
  338. valEnter(oldVal);
  339. return oldVal;
  340. }
  341. void createMT(MotionView v, ToolBar tbar, string group, MType type) { mixin(S_TRACE);
  342. string tt = _prop.msgs.motionName(type);
  343. _descs[type] = .tryFormat(_prop.msgs.msnDesc, group, tt);
  344. class MT {
  345. // FIXME: ?????????
  346. MotionView v;
  347. MType type;
  348. void create() { mixin(S_TRACE);
  349. auto m = new Motion(type, Element.ALL);
  350. m.damageType = DamageType.LEVEL_RATIO;
  351. m.uValue = 1u;
  352. m.aValue = 0;
  353. m.round = v._prop.looks.motionRoundDefault;
  354. m.beast = null;
  355. v.appendMotion(m);
  356. v._motions.select(v._motions.getItemCount() - 1);
  357. v.refreshSels();
  358. foreach (dlg; v.modEvent) dlg();
  359. }
  360. }
  361. auto mt = new MT;
  362. mt.v = v;
  363. mt.type = type;
  364. createToolItem2(_comm, tbar, tt, _prop.images.motion(type), &mt.create, () => !_readOnly);
  365. }
  366. int indexOf(Motion m) { mixin(S_TRACE);
  367. foreach (i, itm; _motions.getItems()) { mixin(S_TRACE);
  368. if (m is itm.getData()) return i;
  369. }
  370. return -1;
  371. }
  372. private EffectCardDialog!(BeastCard) _beastDlg = null;
  373. void editBeastM() { mixin(S_TRACE);
  374. editBeast();
  375. }
  376. EffectCardDialog!BeastCard editBeast() { mixin(S_TRACE);
  377. auto m = selection;
  378. if (m && m.detail.use(MArg.BEAST)) { mixin(S_TRACE);
  379. auto b = m.beast;
  380. if (b) { mixin(S_TRACE);
  381. if (0 != b.linkId) { mixin(S_TRACE);
  382. if (_readOnly) { mixin(S_TRACE);
  383. b = _summ.beast(b.linkId);
  384. if (!b) return null;
  385. } else { mixin(S_TRACE);
  386. auto b2 = _summ.beast(b.linkId);
  387. if (b2) { mixin(S_TRACE);
  388. _comm.openCWXPath(b2.cwxPath(true), false);
  389. return _comm.openBeastWin(false).edit(b2);
  390. }
  391. }
  392. return null;
  393. }
  394. if (_beastDlg) { mixin(S_TRACE);
  395. _beastDlg.active();
  396. } else { mixin(S_TRACE);
  397. _beastDlg = new EffectCardDialog!(BeastCard)(_comm, _prop, getShell(), _summ, b, _readOnly != SWT.NONE);
  398. _beastDlg.open();
  399. if (!_readOnly) { mixin(S_TRACE);
  400. _beastDlg.applyEvent ~= { mixin(S_TRACE);
  401. storeEdit(indexOf(m));
  402. };
  403. _beastDlg.appliedEvent ~= { mixin(S_TRACE);
  404. foreach (dlg; modEvent) dlg();
  405. };
  406. }
  407. _beastDlg.closeEvent ~= { mixin(S_TRACE);
  408. _beastDlg = null;
  409. };
  410. }
  411. return _beastDlg;
  412. }
  413. }
  414. return null;
  415. }
  416. class EditBeast : MouseAdapter, KeyListener {
  417. override:
  418. void mouseDoubleClick(MouseEvent e) { mixin(S_TRACE);
  419. if (e.button == 1) { mixin(S_TRACE);
  420. editBeast();
  421. }
  422. }
  423. void mouseDown(MouseEvent e) { mixin(S_TRACE);
  424. auto ctrl = cast(Control) e.widget;
  425. ctrl.setFocus();
  426. }
  427. void keyReleased(KeyEvent e) {}
  428. void keyPressed(KeyEvent e) { mixin(S_TRACE);
  429. if (e.character == SWT.CR) { mixin(S_TRACE);
  430. if (editBeast()) { mixin(S_TRACE);
  431. e.doit = false;
  432. }
  433. }
  434. }
  435. }
  436. void swap(int index1, int index2, bool store) { mixin(S_TRACE);
  437. if (store) storeSwap(index1, index2);
  438. auto itm1 = _motions.getItem(index1);
  439. auto itm2 = _motions.getItem(index2);
  440. auto img = itm1.getImage();
  441. auto text = itm1.getText();
  442. auto data = itm1.getData();
  443. itm1.setImage(itm2.getImage());
  444. itm1.setText(itm2.getText());
  445. itm1.setData(itm2.getData());
  446. itm2.setImage(img);
  447. itm2.setText(text);
  448. itm2.setData(data);
  449. foreach (dlg; modEvent) dlg();
  450. }
  451. void up() { mixin(S_TRACE);
  452. int index = _motions.getSelectionIndex();
  453. if (index > 0) { mixin(S_TRACE);
  454. swap(index, index - 1, true);
  455. _motions.select(index - 1);
  456. _comm.refreshToolBar();
  457. }
  458. }
  459. void down() { mixin(S_TRACE);
  460. int index = _motions.getSelectionIndex();
  461. if (index >= 0 && index + 1 < _motions.getItemCount()) { mixin(S_TRACE);
  462. swap(index, index + 1, true);
  463. _motions.select(index + 1);
  464. _comm.refreshToolBar();
  465. }
  466. }
  467. void removeMotion() { mixin(S_TRACE);
  468. removeMotion(-1, true, true, true);
  469. }
  470. void removeMotion(int index, bool callEvent, bool callMod, bool store) { mixin(S_TRACE);
  471. bool oldVan = hasVan;
  472. scope (exit) {
  473. if (callEvent && oldVan != hasVan) {
  474. foreach (we; warningEvent) we();
  475. }
  476. _comm.refreshToolBar();
  477. }
  478. if (-1 == index) { mixin(S_TRACE);
  479. index = _motions.getSelectionIndex();
  480. }
  481. if (index >= 0) { mixin(S_TRACE);
  482. if (store) storeDelete(index);
  483. auto m = cast(Motion) _motions.getItem(index).getData();
  484. assert (m);
  485. if (m.beast) { mixin(S_TRACE);
  486. _comm.delBeast.call(m.beast);
  487. }
  488. _motions.remove(index);
  489. if (index >= _motions.getItemCount()) index--;
  490. if (index >= 0) { mixin(S_TRACE);
  491. _motions.select(index);
  492. }
  493. _oldIndex = -1;
  494. _motions.redraw();
  495. refreshSels();
  496. if (callMod) { mixin(S_TRACE);
  497. foreach (dlg; modEvent) dlg();
  498. }
  499. }
  500. }
  501. void appendMotion(Motion motion, int index = -1, bool callEvent = true, bool callMod = false, bool store = true) { mixin(S_TRACE);
  502. bool oldVan;
  503. if (callEvent) { mixin(S_TRACE);
  504. oldVan = hasVan;
  505. }
  506. scope (exit) {
  507. if (callEvent && oldVan != hasVan) {
  508. foreach (we; warningEvent) we();
  509. }
  510. _comm.refreshToolBar();
  511. }
  512. TableItem itm;
  513. if (store) { mixin(S_TRACE);
  514. storeInsert(0 <= index ? index : _motions.getItemCount());
  515. }
  516. if (0 <= index) { mixin(S_TRACE);
  517. itm = new TableItem(_motions, SWT.NONE, index);
  518. } else { mixin(S_TRACE);
  519. itm = new TableItem(_motions, SWT.NONE);
  520. }
  521. itm.setImage(_prop.images.motion(motion.type));
  522. itm.setText(_descs[motion.type]);
  523. itm.setData(motion);
  524. if (callMod) { mixin(S_TRACE);
  525. foreach (dlg; modEvent) dlg();
  526. }
  527. }
  528. Composite _editComp;
  529. Composite _noneComp;
  530. Composite _valueComp;
  531. Composite _roundComp;
  532. Composite _abilityComp;
  533. Composite _summonComp;
  534. int _oldIndex = -1;
  535. void refreshSels(bool force = false) { mixin(S_TRACE);
  536. scope(exit) refEnabled();
  537. auto sels = _motions.getSelection();
  538. auto stack = cast(StackLayout) _editComp.getLayout();
  539. _motionElm.setEnabled(!_readOnly && sels.length > 0);
  540. if (sels.length == 0) { mixin(S_TRACE);
  541. _motionElm.deselectAll();
  542. stack.topControl = _noneComp;
  543. _editComp.layout();
  544. _oldIndex = -1;
  545. } else if (force || _oldIndex != _motions.getSelectionIndex()) { mixin(S_TRACE);
  546. _oldIndex = _motions.getSelectionIndex();
  547. auto m = cast(Motion) _motions.getItem(_oldIndex).getData();
  548. foreach (i, itm; _motionElm.getItems()) { mixin(S_TRACE);
  549. if ((cast(Element) (cast(Integer) itm.getData()).intValue()) == m.element) { mixin(S_TRACE);
  550. _motionElm.select(i);
  551. break;
  552. }
  553. }
  554. auto d = m.detail;
  555. if (d.use(MArg.BEAST)) { mixin(S_TRACE);
  556. _beasts.select(0);
  557. _selectedBeast = null;
  558. _maxNest.setSelection(m.maxNest);
  559. _beastImg.redraw();
  560. if (stack.topControl !is _summonComp) { mixin(S_TRACE);
  561. stack.topControl = _summonComp;
  562. _editComp.layout();
  563. }
  564. } else if (d.use(MArg.ROUND) && d.use(MArg.A_VALUE)) { mixin(S_TRACE);
  565. _abiVal.setSelection(m.aValue + Motion.aValue_max);
  566. _abiRound.setSelection(m.round);
  567. if (stack.topControl !is _abilityComp) { mixin(S_TRACE);
  568. stack.topControl = _abilityComp;
  569. _editComp.layout();
  570. }
  571. } else if (d.use(MArg.ROUND)) { mixin(S_TRACE);
  572. _rndRound.setSelection(m.round);
  573. if (stack.topControl !is _roundComp) { mixin(S_TRACE);
  574. stack.topControl = _roundComp;
  575. _editComp.layout();
  576. }
  577. } else if (d.use(MArg.U_VALUE)) { mixin(S_TRACE);
  578. foreach (typ, radio; _dmgTyp) { mixin(S_TRACE);
  579. _dmgTyp[typ].setSelection((typ == m.damageType));
  580. }
  581. _valValue.setSelection(m.uValue);
  582. if (stack.topControl !is _valueComp) { mixin(S_TRACE);
  583. stack.topControl = _valueComp;
  584. _editComp.layout();
  585. }
  586. } else { mixin(S_TRACE);
  587. if (stack.topControl !is _noneComp) { mixin(S_TRACE);
  588. stack.topControl = _noneComp;
  589. _editComp.layout();
  590. }
  591. }
  592. }
  593. _comm.refreshToolBar();
  594. }
  595. class ParamPaneChange : SelectionAdapter {
  596. override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  597. refreshSels();
  598. }
  599. }
  600. bool canSetBeast() { mixin(S_TRACE);
  601. if (_readOnly) return false;
  602. if (_selectedBeast) return true;
  603. int mi = _motions.getSelectionIndex();
  604. if (-1 == mi) return false;
  605. auto sb = cast(Motion) _motions.getItem(mi).getData();
  606. // ????????????
  607. return sb.beast !is null;
  608. }
  609. class SetBeast : SelectionAdapter {
  610. override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  611. auto b = _selectedBeast;
  612. int mi = _motions.getSelectionIndex();
  613. assert (-1 != mi);
  614. auto sb = cast(Motion) _motions.getItem(mi).getData();
  615. if (b) { mixin(S_TRACE);
  616. if (!sb.beast && !b) return;
  617. storeEdit(mi);
  618. if (sb.beast) _comm.delBeast.call(sb.beast);
  619. if (_prop.var.etc.linkCard) { mixin(S_TRACE);
  620. sb.beast = new BeastCard(1UL, "", "", "");
  621. sb.beast.linkId = b.id;
  622. } else { mixin(S_TRACE);
  623. sb.beast = b;
  624. }
  625. } else { mixin(S_TRACE);
  626. if (!sb.beast) return;
  627. storeEdit(mi);
  628. _comm.delBeast.call(sb.beast);
  629. sb.beast = null;
  630. }
  631. resetMaxNest(sb);
  632. _beastImg.redraw();
  633. foreach (dlg; modEvent) dlg();
  634. refEnabled();
  635. _comm.refreshToolBar();
  636. }
  637. }
  638. void removeRef() { mixin(S_TRACE);
  639. auto m = selection;
  640. if (!m || !m.beast || 0 == m.beast.linkId) return;
  641. auto targ = _summ.beast(m.beast.linkId);
  642. if (!targ) return;
  643. storeEdit(_motions.getSelectionIndex());
  644. auto id = m.beast.id;
  645. m.beast.deepCopy(targ);
  646. m.beast.id = id;
  647. m.beast.linkId = 0;
  648. resetMaxNest(m);
  649. _beastImg.redraw();
  650. foreach (dlg; modEvent) dlg();
  651. refEnabled();
  652. }
  653. class PaintBeast : PaintListener {
  654. override void paintControl(PaintEvent e) { mixin(S_TRACE);
  655. auto beast = selection.beast;
  656. if (beast) { mixin(S_TRACE);
  657. scope img = new Image(Display.getCurrent(),
  658. cardImage!(BeastCard)(_prop, summSkin, beast, _summ.scenarioPath, null, &_summ.beast, true, false));
  659. scope data = img.getImageData();
  660. auto pane = cast(Canvas) e.widget;
  661. scope rect = pane.getClientArea();
  662. int x = (rect.width - data.width) / 2;
  663. int y = (rect.height - data.height) / 2;
  664. e.gc.drawImage(img, x, y);
  665. img.dispose();
  666. if (pane.isFocusControl()) { mixin(S_TRACE);
  667. e.gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_LIST_SELECTION));
  668. e.gc.setAlpha(64);
  669. e.gc.fillRectangle(x, y, data.width, data.height);
  670. e.gc.setAlpha(255);
  671. }
  672. }
  673. }
  674. }
  675. class MDropListener : DropTargetAdapter {
  676. override void dragEnter(DropTargetEvent e){ mixin(S_TRACE);
  677. e.detail = _readOnly ? DND.DROP_NONE : DND.DROP_MOVE;
  678. }
  679. override void dragOver(DropTargetEvent e){ mixin(S_TRACE);
  680. e.detail = _readOnly ? DND.DROP_NONE : DND.DROP_MOVE;
  681. }
  682. override void drop(DropTargetEvent e){ mixin(S_TRACE);
  683. if (!isXMLBytes(e.data)) return;
  684. e.detail = DND.DROP_NONE;
  685. string xml = bytesToXML(e.data);
  686. try { mixin(S_TRACE);
  687. auto node = XNode.parse(xml);
  688. if (node.name != Motion.XML_NAME) return;
  689. scope p = (cast(DropTarget) e.getSource()).getControl().toControl(e.x, e.y);
  690. auto t = _motions.getItem(p);
  691. int index = t ? _motions.indexOf(t) : _motions.getItemCount();
  692. auto ver = new XMLInfo(_prop.sys, LATEST_VERSION);
  693. auto m = Motion.createFromNode(node, ver);
  694. if (_id == node.attr("paneId", false)) { mixin(S_TRACE);
  695. if (-1 != _dragIndex) { mixin(S_TRACE);
  696. storeMove(_dragIndex, index);
  697. appendMotion(m, index, true, false, false);
  698. } else { mixin(S_TRACE);
  699. appendMotion(m, index, true, false, true);
  700. }
  701. _motions.select(index);
  702. refreshSels();
  703. e.detail = DND.DROP_MOVE;
  704. } else { mixin(S_TRACE);
  705. appendMotion(m, index, true, false, true);
  706. }
  707. foreach (dlg; modEvent) dlg();
  708. } catch {}
  709. }
  710. }
  711. private int _dragIndex = -1;
  712. class MDragListener : DragSourceAdapter {
  713. private TableItem _itm;
  714. override void dragStart(DragSourceEvent e) { mixin(S_TRACE);
  715. e.doit = (cast(DragSource) e.getSource()).getControl().isFocusControl();
  716. }
  717. override void dragSetData(DragSourceEvent e){ mixin(S_TRACE);
  718. if (XMLBytesTransfer.getInstance().isSupportedType(e.dataType)) { mixin(S_TRACE);
  719. auto c = cast(Table) (cast(DragSource) e.getSource()).getControl();
  720. int index = c.getSelectionIndex();
  721. if (index >= 0) { mixin(S_TRACE);
  722. auto m = cast(Motion) c.getItem(index).getData();
  723. _dragIndex = index;
  724. auto node = m.toNode(new XMLOption(_prop.sys));
  725. node.newAttr("paneId", _id);
  726. e.data = bytesFromXML(node.text);
  727. _itm = c.getItem(index);
  728. }
  729. }
  730. }
  731. override void dragFinished(DragSourceEvent e) { mixin(S_TRACE);
  732. _dragIndex = -1;
  733. if (!_readOnly && e.detail == DND.DROP_MOVE) { mixin(S_TRACE);
  734. bool oldVan = hasVan;
  735. scope (exit) {
  736. if (oldVan != hasVan) {
  737. foreach (we; warningEvent) we();
  738. }
  739. }
  740. _itm.dispose();
  741. _motions.redraw();
  742. foreach (dlg; modEvent) dlg();
  743. _comm.refreshToolBar();
  744. }
  745. }
  746. }
  747. @property
  748. bool hasVan() { mixin(S_TRACE);
  749. foreach (itm; _motions.getItems()) { mixin(S_TRACE);
  750. auto m = cast(Motion) itm.getData();
  751. assert (m);
  752. if ((m.element !is Element.MIRACLE) && (m.type is MType.VANISH_TARGET)) { mixin(S_TRACE);
  753. return true;
  754. }
  755. }
  756. return false;
  757. }
  758. class SelElement : SelectionAdapter {
  759. override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  760. auto m = selection;
  761. if (m) { mixin(S_TRACE);
  762. int i = _motionElm.getSelectionIndex();
  763. if (-1 == i) return;
  764. storeEdit(_motions.getSelectionIndex());
  765. bool oldVan = hasVan;
  766. scope (exit) {
  767. if (oldVan != hasVan) {
  768. foreach (we; warningEvent) we();
  769. }
  770. }
  771. m.element = cast(Element) (cast(Integer) _motionElm.getItem(i).getData()).intValue();
  772. foreach (dlg; modEvent) dlg();
  773. }
  774. }
  775. }
  776. class Dispose : DisposeListener {
  777. override void widgetDisposed(DisposeEvent e) { mixin(S_TRACE);
  778. _comm.refMenu.remove(&refMenu);
  779. _comm.refBeast.remove(&refBeast);
  780. _comm.delBeast.remove(&refBeast);
  781. _comm.refUndoMax.remove(&refUndoMax);
  782. getDisplay().removeFilter(SWT.KeyDown, _kdFilter);
  783. foreach (w; _beWin.toArray()) { mixin(S_TRACE);
  784. _comm.close(w.shell);
  785. }
  786. }
  787. }
  788. class KeyDownFilter : Listener {
  789. this () { mixin(S_TRACE);
  790. refMenu(MenuID.Undo);
  791. refMenu(MenuID.Redo);
  792. }
  793. override void handleEvent(Event e) { mixin(S_TRACE);
  794. auto c = cast(Control) e.widget;
  795. if (!c || c.getShell() !is getShell()) return;
  796. if (!isDescendant(this.outer, c)) return;
  797. if (eqAcc(_undoAcc, e.keyCode, e.character, e.stateMask)) { mixin(S_TRACE);
  798. _undo.undo();
  799. e.doit = false;
  800. } else if (eqAcc(_redoAcc, e.keyCode, e.character, e.stateMask)) { mixin(S_TRACE);
  801. _undo.redo();
  802. e.doit = false;
  803. }
  804. }
  805. }
  806. private int _undoAcc;
  807. private int _redoAcc;
  808. void refMenu(MenuID id) { mixin(S_TRACE);
  809. if (id == MenuID.Undo) _undoAcc = convertAccelerator(_prop.buildMenu(MenuID.Undo));
  810. if (id == MenuID.Redo) _redoAcc = convertAccelerator(_prop.buildMenu(MenuID.Redo));
  811. }
  812. void refBeast(BeastCard beast) { mixin(S_TRACE);
  813. refBeasts();
  814. }
  815. void refBeasts() { mixin(S_TRACE);
  816. setRedraw(false);
  817. scope (exit) setRedraw(true);
  818. ulong selId = 0;
  819. auto sel = _selectedBeast;
  820. if (sel) selId = sel.id;
  821. _beasts.removeAll();
  822. typeof(_beastTbl) b;
  823. _beastTbl = b;
  824. _beasts.add(_prop.msgs.beastNone);
  825. _beastTbl[0] = null;
  826. size_t i = 0;
  827. bool has = false;
  828. foreach (c; _summ.beasts) { mixin(S_TRACE);
  829. if (!has && selId == c.id) { mixin(S_TRACE);
  830. has = true;
  831. }
  832. if (!_beastIncSearch.match(c.name)) continue;
  833. _beastTbl[i + 1] = c;
  834. _beasts.add(to!string(c.id) ~ "." ~ c.name);
  835. if (c.id == selId) { mixin(S_TRACE);
  836. _beasts.select(_beasts.getItemCount() - 1);
  837. _selectedBeast = c;
  838. }
  839. i++;
  840. }
  841. if (!has) { mixin(S_TRACE);
  842. _beasts.select(0);
  843. _selectedBeast = null;
  844. }
  845. refEnabled();
  846. }
  847. void openBeastCardView() { mixin(S_TRACE);
  848. if (!_selectedBeast) return;
  849. try { mixin(S_TRACE);
  850. _comm.openCWXPath(cpaddattr(_selectedBeast.cwxPath(true), "shallow"), false);
  851. } catch (Exception e) {
  852. debugln(e);
  853. }
  854. }
  855. bool _refUndo = false;
  856. void refUndoMax() { mixin(S_TRACE);
  857. if (!_refUndo) return;
  858. _undo.max = _prop.var.etc.undoMaxEtc;
  859. }
  860. public:
  861. this (Commons comm, Props prop, Summary summ, Composite parent, int style, UndoManager undo = null) { mixin(S_TRACE);
  862. super(parent, SWT.NONE);
  863. _id = format("%08X", &this) ~ "-" ~ to!(string)(Clock.currTime());
  864. _readOnly = style & SWT.READ_ONLY;
  865. _comm = comm;
  866. _prop = prop;
  867. _summ = summ;
  868. if (_readOnly) _summSkin = findSkin(_comm, _prop, _summ);
  869. _refUndo = undo is null;
  870. _undo = undo ? undo : new UndoManager(_prop.var.etc.undoMaxEtc);
  871. _beWin = new typeof(_beWin);
  872. setLayout(zeroMarginGridLayout(3, false));
  873. { mixin(S_TRACE);
  874. auto mtabf = new CTabFolder(this, SWT.FLAT | SWT.BORDER);
  875. auto gd = new GridData(GridData.FILL_HORIZONTAL);
  876. gd.widthHint = 0;
  877. gd.horizontalSpan = 3;
  878. mtabf.setLayoutData(gd);
  879. ToolBar createBar(string name) { mixin(S_TRACE);
  880. auto bar = new ToolBar(mtabf, SWT.FLAT);
  881. _comm.put(bar);
  882. bar.setEnabled(!_readOnly);
  883. bar.addListener(SWT.Traverse, new class Listener {
  884. override void handleEvent(Event e) {e.doit = true;}
  885. });
  886. bar.addListener(SWT.KeyDown, new class Listener {
  887. override void handleEvent(Event e) {e.doit = true;}
  888. });
  889. createToolItem2(_comm, bar, _prop.msgs.msnDelete, _prop.images.msnDelete, &removeMotion, () => _motions.getSelectionIndex() != -1);
  890. new ToolItem(bar, SWT.SEPARATOR);
  891. createToolItem(_comm, bar, MenuID.Up, &up, () => _motions.getSelectionIndex() != -1 && 0 < _motions.getSelectionIndex());
  892. createToolItem(_comm, bar, MenuID.Down, &down, () => _motions.getSelectionIndex() != -1 && _motions.getSelectionIndex() + 1 < _motions.getItemCount());
  893. new ToolItem(bar, SWT.SEPARATOR);
  894. auto tab = new CTabItem(mtabf, SWT.NONE);
  895. tab.setControl(bar);
  896. tab.setText(name);
  897. return bar;
  898. }
  899. { mixin(S_TRACE);
  900. string g = _prop.msgs.msnGroupVitality;
  901. auto bar = createBar(g);
  902. createMT(this, bar, g, MType.HEAL);
  903. createMT(this, bar, g, MType.DAMAGE);
  904. createMT(this, bar, g, MType.ABSORB);
  905. }
  906. { mixin(S_TRACE);
  907. string g = _prop.msgs.msnGroupPhysical;
  908. auto bar = createBar(g);
  909. createMT(this, bar, g, MType.PARALYZE);
  910. createMT(this, bar, g, MType.DIS_PARALYZE);
  911. createMT(this, bar, g, MType.POISON);
  912. createMT(this, bar, g, MType.DIS_POISON);
  913. }
  914. { mixin(S_TRACE);
  915. string g = _prop.msgs.msnGroupSkill;
  916. auto bar = createBar(g);
  917. createMT(this, bar, g, MType.GET_SKILL_POWER);
  918. createMT(this, bar, g, MType.LOSE_SKILL_POWER);
  919. }
  920. { mixin(S_TRACE);
  921. string g = _prop.msgs.msnGroupMental;
  922. auto bar = createBar(g);
  923. createMT(this, bar, g, MType.SLEEP);
  924. createMT(this, bar, g, MType.CONFUSE);
  925. createMT(this, bar, g, MType.OVERHEAT);
  926. createMT(this, bar, g, MType.BRAVE);
  927. createMT(this, bar, g, MType.PANIC);
  928. createMT(this, bar, g, MType.NORMAL);
  929. }
  930. { mixin(S_TRACE);
  931. string g = _prop.msgs.msnGroupMagic;
  932. auto bar = createBar(g);
  933. createMT(this, bar, g, MType.BIND);
  934. createMT(this, bar, g, MType.DIS_BIND);
  935. createMT(this, bar, g, MType.SILENCE);
  936. createMT(this, bar, g, MType.DIS_SILENCE);
  937. createMT(this, bar, g, MType.FACE_UP);
  938. createMT(this, bar, g, MType.FACE_DOWN);
  939. createMT(this, bar, g, MType.ANTI_MAGIC);
  940. createMT(this, bar, g, MType.DIS_ANTI_MAGIC);
  941. }
  942. { mixin(S_TRACE);
  943. string g = _prop.msgs.msnGroupEnhance;
  944. auto bar = createBar(g);
  945. createMT(this, bar, g, MType.ENHANCE_ACTION);
  946. createMT(this, bar, g, MType.ENHANCE_AVOID);
  947. createMT(this, bar, g, MType.ENHANCE_DEFENSE);
  948. createMT(this, bar, g, MType.ENHANCE_RESIST);
  949. }
  950. { mixin(S_TRACE);
  951. string g = _prop.msgs.msnGroupVanish;
  952. auto bar = createBar(g);
  953. createMT(this, bar, g, MType.VANISH_TARGET);
  954. createMT(this, bar, g, MType.VANISH_CARD);
  955. createMT(this, bar, g, MType.VANISH_BEAST);
  956. }
  957. { mixin(S_TRACE);
  958. string g = _prop.msgs.msnGroupCard;
  959. auto bar = createBar(g);
  960. createMT(this, bar, g, MType.DEAL_ATTACK_CARD);
  961. createMT(this, bar, g, MType.DEAL_POWERFUL_ATTACK_CARD);
  962. createMT(this, bar, g, MType.DEAL_CRITICAL_ATTACK_CARD);
  963. createMT(this, bar, g, MType.DEAL_FEINT_CARD);
  964. createMT(this, bar, g, MType.DEAL_DEFENSE_CARD);
  965. createMT(this, bar, g, MType.DEAL_DISTANCE_CARD);
  966. createMT(this, bar, g, MType.DEAL_CONFUSE_CARD);
  967. createMT(this, bar, g, MType.DEAL_SKILL_CARD);
  968. createMT(this, bar, g, MType.CANCEL_ACTION); // CardWirth 1.50
  969. }
  970. { mixin(S_TRACE);
  971. string g = _prop.msgs.msnGroupBeast;
  972. auto bar = createBar(g);
  973. createMT(this, bar, g, MType.SUMMON_BEAST);
  974. }
  975. mtabf.setSelection(0);
  976. }
  977. { mixin(S_TRACE);
  978. _motions = new Table(this, SWT.BORDER | SWT.SINGLE | SWT.V_SCROLL | SWT.FULL_SELECTION);
  979. auto gd = new GridData(GridData.FILL_BOTH);
  980. gd.widthHint = _prop.var.etc.motionsWidth;
  981. _motions.setLayoutData(gd);
  982. _motions.setHeaderVisible(true);
  983. auto menu = new Menu(_motions);
  984. if (!_readOnly) { mixin(S_TRACE);
  985. createMenuItem(_comm, menu, MenuID.Undo, &this.undo, () => !_readOnly && _undo.canUndo);
  986. createMenuItem(_comm, menu, MenuID.Redo, &this.redo, () => !_readOnly && _undo.canRedo);
  987. new MenuItem(menu, SWT.SEPARATOR);
  988. createMenuItem(_comm, menu, MenuID.Up, &up, () => !_readOnly && _motions.getSelectionIndex() != -1 && 0 < _motions.getSelectionIndex());
  989. createMenuItem(_comm, menu, MenuID.Down, &down, () => !_readOnly && _motions.getSelectionIndex() != -1 && _motions.getSelectionIndex() + 1 < _motions.getItemCount());
  990. new MenuItem(menu, SWT.SEPARATOR);
  991. appendMenuTCPD(_comm, menu, new MotionTCPD, true, true, true, true, true);
  992. } else { mixin(S_TRACE);
  993. appendMenuTCPD(_comm, menu, new MotionTCPD, false, true, false, false, false);
  994. }
  995. _motions.setMenu(menu);
  996. auto col = new FullTableColumn(_motions, SWT.NONE);
  997. col.column.setText(_prop.msgs.motionKind);
  998. }
  999. { mixin(S_TRACE);
  1000. _motionElm = new Table(this, SWT.BORDER | SWT.SINGLE | SWT.NO_SCROLL | SWT.FULL_SELECTION);
  1001. _motionElm.setLayoutData(new GridData(GridData.FILL_VERTICAL));
  1002. _motionElm.setHeaderVisible(true);
  1003. _motionElm.addSelectionListener(new SelElement);
  1004. _motionElm.setEnabled(false);
  1005. auto col = new FullTableColumn(_motionElm, SWT.NONE);
  1006. col.column.setText(_prop.msgs.motionElement);
  1007. string[] toolTip;
  1008. foreach (i, elm; [Element.ALL, Element.HEALTH, Element.MIND,
  1009. Element.MIRACLE, Element.MAGIC, Element.FIRE, Element.ICE]) { mixin(S_TRACE);
  1010. auto itm = new TableItem(_motionElm, SWT.NONE);
  1011. itm.setImage(_prop.images.element(elm));
  1012. itm.setText(_prop.msgs.elementName(elm));
  1013. itm.setData(new Integer(elm));
  1014. toolTip ~= _prop.msgs.elementDesc(elm);
  1015. }
  1016. .listener(_motionElm, SWT.MouseMove, (Event e) { mixin(S_TRACE);
  1017. auto itm = _motionElm.getItem(new Point(e.x, e.y));
  1018. if (itm) { mixin(S_TRACE);
  1019. _motionElm.setToolTipText(toolTip[_motionElm.indexOf(itm)]);
  1020. } else { mixin(S_TRACE);
  1021. _motionElm.setToolTipText(null);
  1022. }
  1023. });
  1024. auto menu = new Menu(_motionElm);
  1025. createMenuItem(_comm, menu, MenuID.Undo, &this.undo, () => !_readOnly && _undo.canUndo);
  1026. createMenuItem(_comm, menu, MenuID.Redo, &this.redo, () => !_readOnly && _undo.canRedo);
  1027. _motionElm.setMenu(menu);
  1028. }
  1029. { mixin(S_TRACE);
  1030. _editComp = new Composite(this, SWT.NONE);
  1031. _editComp.setLayoutData(new GridData(GridData.FILL_VERTICAL));
  1032. auto motionStack = new StackLayout;
  1033. _editComp.setLayout(motionStack);
  1034. Composite createC() { mixin(S_TRACE);
  1035. auto c = new Composite(_editComp, SWT.NONE);
  1036. c.setLayout(zeroMarginGridLayout(1, false));
  1037. return c;
  1038. }
  1039. _summonComp = createC();
  1040. { mixin(S_TRACE);
  1041. auto grp = new Group(_summonComp, SWT.NONE);
  1042. grp.setLayoutData(new GridData(GridData.FILL_BOTH));
  1043. grp.setLayout(new GridLayout(2, false));
  1044. grp.setText(_prop.msgs.motionBeast);
  1045. _beasts = new Combo(grp, SWT.BORDER | SWT.DROP_DOWN | SWT.READ_ONLY);
  1046. _beasts.setEnabled(!_readOnly);
  1047. _beasts.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  1048. _beasts.addSelectionListener(new class SelectionAdapter {
  1049. override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  1050. auto index = _beasts.getSelectionIndex();
  1051. _selectedBeast = -1 != index ? _beastTbl[index] : null;
  1052. _comm.refreshToolBar();
  1053. }
  1054. });
  1055. _beastIncSearch = new IncSearch(_comm, _beasts);
  1056. _beastIncSearch.modEvent ~= &refBeasts;
  1057. { mixin(S_TRACE);
  1058. auto menu = new Menu(_beasts.getShell(), SWT.POP_UP);
  1059. createMenuItem(_comm, menu, MenuID.IncSearch, &beastIncSearch, () => !_readOnly && 1 < _beasts.getItemCount());
  1060. new MenuItem(menu, SWT.SEPARATOR);
  1061. createMenuItem(_comm, menu, MenuID.OpenAtCardView, &openBeastCardView, () => !_readOnly && 0 < _beasts.getSelectionIndex());
  1062. _beasts.setMenu(menu);
  1063. }
  1064. refBeasts();
  1065. auto setBeast = new Button(grp, SWT.PUSH);
  1066. setBeast.setEnabled(!_readOnly);
  1067. setBeast.setImage(_prop.images.setBeast);
  1068. setBeast.setToolTipText(_prop.msgs.setBeast);
  1069. setBeast.addSelectionListener(new SetBeast);
  1070. _comm.put(setBeast, &canSetBeast);
  1071. _beastImg = new Canvas(grp, SWT.BORDER | SWT.DOUBLE_BUFFERED);
  1072. _beastImg.addListener(SWT.Traverse, new class Listener {
  1073. override void handleEvent(Event e) { mixin(S_TRACE);
  1074. e.doit = true;
  1075. }
  1076. });
  1077. _beastImg.addListener(SWT.KeyDown, new class Listener {
  1078. override void handleEvent(Event e) { mixin(S_TRACE);
  1079. e.doit = true;
  1080. }
  1081. });
  1082. _beastImg.addListener(SWT.MouseDown, new class Listener {
  1083. override void handleEvent(Event e) { mixin(S_TRACE);
  1084. if (e.button == 1) (cast(Canvas) e.widget).setFocus();
  1085. }
  1086. });
  1087. _beastImg.addListener(SWT.FocusOut, new class Listener {
  1088. override void handleEvent(Event e) { mixin(S_TRACE);
  1089. (cast(Canvas) e.widget).redraw();
  1090. }
  1091. });
  1092. _beastImg.addListener(SWT.FocusIn, new class Listener {
  1093. override void handleEvent(Event e) { mixin(S_TRACE);
  1094. (cast(Canvas) e.widget).redraw();
  1095. }
  1096. });
  1097. _beastImg.addPaintListener(new PaintBeast);
  1098. auto eb = new EditBeast;
  1099. _beastImg.addMouseListener(eb);
  1100. _beastImg.addKeyListener(eb);
  1101. auto menu = new Menu(_beastImg);
  1102. if (_readOnly) { mixin(S_TRACE);
  1103. createMenuItem(_comm, menu, MenuID.ShowProp, &editBeastM, &canEditBeast);
  1104. } else { mixin(S_TRACE);
  1105. createMenuItem(_comm, menu, MenuID.EditProp, &editBeastM, &canEditBeast);
  1106. }
  1107. new MenuItem(menu, SWT.SEPARATOR);
  1108. createMenuItem(_comm, menu, MenuID.EditEventAtTimeOfUsing, &editBeastUseEvent, &canEditBeast);
  1109. new MenuItem(menu, SWT.SEPARATOR);
  1110. createMenuItem(_comm, menu, MenuID.RemoveRef, &removeRef, () => !_readOnly && selection && selection.beast && 0 != selection.beast.linkId && _summ.beast(selection.beast.linkId));
  1111. new MenuItem(menu, SWT.SEPARATOR);
  1112. createMenuItem(_comm, menu, MenuID.Undo, &this.undo, () => !_readOnly && _undo.canUndo);
  1113. createMenuItem(_comm, menu, MenuID.Redo, &this.redo, () => !_readOnly && _undo.canRedo);
  1114. new MenuItem(menu, SWT.SEPARATOR);
  1115. appendMenuTCPD(_comm, menu, new BeastTCPD, true, true, true, true, false);
  1116. _beastImg.setMenu(menu);
  1117. auto gd = new GridData(GridData.FILL_BOTH);
  1118. gd.horizontalSpan = 2;
  1119. auto csize = _prop.looks.cardSize;
  1120. auto mat = _prop.looks.menuCardInsets;
  1121. csize.width += mat.e + mat.w;
  1122. csize.height += mat.n + mat.s;
  1123. auto rect = _beastImg.computeTrim(0, 0, csize.width, csize.height);
  1124. gd.widthHint = rect.width;
  1125. gd.heightHint = rect.height;
  1126. _beastImg.setLayoutData(gd);
  1127. auto grp2 = new Group(_summonComp, SWT.NONE);
  1128. grp2.setText(_prop.msgs.linkOption);
  1129. auto gd2 = new GridData(GridData.FILL_HORIZONTAL);
  1130. gd2.horizontalSpan = 2;
  1131. grp2.setLayoutData(gd2);
  1132. grp2.setLayout(new CenterLayout);
  1133. auto comp2 = new Composite(grp2, SWT.NONE);
  1134. comp2.setLayout(zeroMarginGridLayout(2, false));
  1135. auto l = new Label(comp2, SWT.NONE);
  1136. l.setText(_prop.msgs.beastMaxNest);
  1137. _maxNest = new Spinner(comp2, SWT.BORDER);
  1138. initSpinner(_maxNest);
  1139. .listener(_maxNest, SWT.Modify, { mixin(S_TRACE);
  1140. auto m = selection;
  1141. if (!m) return;
  1142. m.maxNest = _maxNest.getSelection();
  1143. foreach (dlg; modEvent) dlg();
  1144. });
  1145. _maxNest.setMinimum(1);
  1146. _maxNest.setMaximum(_prop.var.etc.beastMaxNest);
  1147. }
  1148. Spinner createSpinner(Composite parent, string name, int max, string hint,
  1149. void delegate(int) edit, int delegate(int) cancel) { mixin(S_TRACE);
  1150. auto rgrp = new Group(parent, SWT.NONE);
  1151. rgrp.setText(name);
  1152. rgrp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  1153. rgrp.setLayout(new CenterLayout(SWT.VERTICAL | SWT.HORIZONTAL, 0));
  1154. auto rcomp = new Composite(rgrp, SWT.NONE);
  1155. rcomp.setLayout(new GridLayout(2, false));
  1156. auto round = new Spinner(rcomp, SWT.BORDER | _readOnly);
  1157. initSpinner(round);
  1158. round.setMaximum(max);
  1159. round.setMinimum(1);
  1160. new SpinnerEdit(round, edit, edit, cancel);
  1161. auto l_round = new Label(rcomp, SWT.NONE);
  1162. l_round.setText(hint);
  1163. return round;
  1164. }
  1165. Spinner createRoundC(Composite parent) { mixin(S_TRACE);
  1166. return createSpinner(parent, _prop.msgs.motionRound, _prop.var.etc.roundMax,
  1167. .tryFormat(_prop.msgs.rangeHint, 1, _prop.var.etc.roundMax), &roundEnter, &roundCancel);
  1168. }
  1169. _abilityComp = createC();
  1170. { mixin(S_TRACE);
  1171. auto vgrp = new Group(_abilityComp, SWT.NONE);
  1172. vgrp.setText(_prop.msgs.motionEnhValue);
  1173. vgrp.setLayout(new CenterLayout(SWT.VERTICAL | SWT.HORIZONTAL, 0));
  1174. auto vcomp = new Composite(vgrp, SWT.NONE);
  1175. vcomp.setLayout(new GridLayout(2, false));
  1176. _abiVal = new Scale(vcomp, SWT.NONE);
  1177. _abiVal.setEnabled(!_readOnly);
  1178. auto gd_av = new GridData(GridData.FILL_HORIZONTAL);
  1179. gd_av.horizontalSpan = 2;
  1180. _abiVal.setLayoutData(gd_av);
  1181. _abiVal.setMinimum(0);
  1182. _abiVal.setMaximum(Motion.aValue_max - Motion.aValue_min);
  1183. _abiVal.setPageIncrement(Motion.aValue_max / 2);
  1184. _abiVal.addSelectionListener(new AbiValListener);
  1185. auto l_min = new Label(vcomp, SWT.NONE);
  1186. l_min.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
  1187. l_min.setText(to!(string)(Motion.aValue_min));
  1188. auto l_max = new Label(vcomp, SWT.NONE);
  1189. l_max.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
  1190. l_max.setText("+" ~ to!(string)(Motion.aValue_max));
  1191. _abiRound = createRoundC(_abilityComp);
  1192. }
  1193. _roundComp = createC();
  1194. { mixin(S_TRACE);
  1195. _rndRound = createRoundC(_roundComp);
  1196. }
  1197. _valueComp = createC();
  1198. { mixin(S_TRACE);
  1199. auto grp = new Group(_valueComp, SWT.NONE);
  1200. grp.setText(_prop.msgs.motionDamageType);
  1201. grp.setLayout(new CenterLayout(SWT.VERTICAL | SWT.HORIZONTAL, 0));
  1202. grp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  1203. auto comp = new Composite(grp, SWT.NONE);
  1204. comp.setLayout(new GridLayout(1, false));
  1205. auto dtl = new DamageTypeListener;
  1206. foreach (typ; [DamageType.LEVEL_RATIO, DamageType.NORMAL, DamageType.MAX]) { mixin(S_TRACE);
  1207. auto radio = new Button(comp, SWT.RADIO);
  1208. radio.setEnabled(!_readOnly);
  1209. radio.setText(_prop.msgs.damageTypeName(typ));
  1210. radio.addSelectionListener(dtl);
  1211. _dmgTyp[typ] = radio;
  1212. }
  1213. _valValue = createSpinner(_valueComp, _prop.msgs.motionValue, _prop.var.etc.uValueMax,
  1214. .tryFormat(_prop.msgs.rangeHint, Motion.uValue_min, _prop.var.etc.uValueMax), &valEnter, &valCancel);
  1215. }
  1216. _noneComp = createC();
  1217. motionStack.topControl = _noneComp;
  1218. _motions.addSelectionListener(new ParamPaneChange);
  1219. }
  1220. auto drag = new DragSource(_motions, DND.DROP_MOVE | DND.DROP_COPY);
  1221. drag.setTransfer([XMLBytesTransfer.getInstance()]);
  1222. drag.addDragListener(new MDragListener);
  1223. auto drop = new DropTarget(_motions, DND.DROP_DEFAULT | DND.DROP_MOVE | DND.DROP_COPY);
  1224. drop.setTransfer([XMLBytesTransfer.getInstance()]);
  1225. drop.addDropListener(new MDropListener);
  1226. addDisposeListener(new Dispose);
  1227. _kdFilter = new KeyDownFilter();
  1228. _comm.refMenu.add(&refMenu);
  1229. _comm.refBeast.add(&refBeast);
  1230. _comm.delBeast.add(&refBeast);
  1231. _comm.refUndoMax.add(&refUndoMax);
  1232. getDisplay().addFilter(SWT.KeyDown, _kdFilter);
  1233. }
  1234. void refEnabled() { mixin(S_TRACE);
  1235. auto m = selection();
  1236. if (_maxNest) _maxNest.setEnabled(!_readOnly && m && m.beast && 0 != m.beast.linkId);
  1237. }
  1238. @property
  1239. void motions(Motion[] motions) { mixin(S_TRACE);
  1240. bool oldVan = hasVan;
  1241. scope (exit) {
  1242. if (oldVan != hasVan) {
  1243. foreach (we; warningEvent) we();
  1244. }
  1245. }
  1246. _motions.setRedraw(false);
  1247. _undo.reset();
  1248. foreach (i, m; motions) { mixin(S_TRACE);
  1249. appendMotion(m.dup, -1, false, false, false);
  1250. if (0 == i) _motions.select(0);
  1251. }
  1252. refreshSels();
  1253. foreach (dlg; modEvent) dlg();
  1254. _motions.setRedraw(true);
  1255. _comm.refreshToolBar();
  1256. }
  1257. @property
  1258. Motion[] motions() { mixin(S_TRACE);
  1259. Motion[] r;
  1260. r.length = _motions.getItemCount();
  1261. foreach (i, itm; _motions.getItems()) { mixin(S_TRACE);
  1262. r[i] = cast(Motion) itm.getData();
  1263. }
  1264. return r;
  1265. }
  1266. private class MotionTCPD : TCPD {
  1267. override void cut(SelectionEvent se) { mixin(S_TRACE);
  1268. auto m = selection;
  1269. if (m) { mixin(S_TRACE);
  1270. copy(se);
  1271. del(se);
  1272. }
  1273. }
  1274. override void copy(SelectionEvent se) { mixin(S_TRACE);
  1275. auto m = selection;
  1276. if (m) { mixin(S_TRACE);
  1277. XMLtoCB(_prop, _comm.clipboard, m.toXML(new XMLOption(_prop.sys)));
  1278. _comm.refreshToolBar();
  1279. }
  1280. }
  1281. override void paste(SelectionEvent se) { mixin(S_TRACE);
  1282. auto xml = CBtoXML(_comm.clipboard);
  1283. if (xml) { mixin(S_TRACE);
  1284. try { mixin(S_TRACE);
  1285. auto node = XNode.parse(xml);
  1286. if (node.name == Motion.XML_NAME) { mixin(S_TRACE);
  1287. auto ver = new XMLInfo(_prop.sys, LATEST_VERSION);
  1288. appendMotion(Motion.createFromNode(node, ver));
  1289. _motions.select(_motions.getItemCount() - 1);
  1290. refreshSels();
  1291. foreach (dlg; modEvent) dlg();
  1292. } else { mixin(S_TRACE);
  1293. pasteBeast(node);
  1294. }
  1295. _comm.refreshToolBar();
  1296. } catch {}
  1297. }
  1298. }
  1299. override void del(SelectionEvent se) { mixin(S_TRACE);
  1300. removeMotion();
  1301. }
  1302. override void clone(SelectionEvent se) { mixin(S_TRACE);
  1303. _comm.clipboard.memoryMode = true;
  1304. scope (exit) _comm.clipboard.memoryMode = false;
  1305. copy(se);
  1306. paste(se);
  1307. }
  1308. @property
  1309. override bool canDoTCPD() { mixin(S_TRACE);
  1310. return _motions.isFocusControl();
  1311. }
  1312. @property
  1313. override bool canDoT() { mixin(S_TRACE);
  1314. return !_readOnly && _motions.getSelectionIndex() >= 0;
  1315. }
  1316. @property
  1317. override bool canDoC() { mixin(S_TRACE);
  1318. return _motions.getSelectionIndex() >= 0;
  1319. }
  1320. @property
  1321. override bool canDoP() { mixin(S_TRACE);
  1322. return !_readOnly && CBisXML(_comm.clipboard);
  1323. }
  1324. @property
  1325. override bool canDoD() { mixin(S_TRACE);
  1326. return canDoT;
  1327. }
  1328. @property
  1329. override bool canDoClone() { mixin(S_TRACE);
  1330. return !_readOnly && canDoC;
  1331. }
  1332. }
  1333. private void pasteBeast(ref XNode node) { mixin(S_TRACE);
  1334. auto m = selection;
  1335. if (m && m.detail.use(MArg.BEAST)) { mixin(S_TRACE);
  1336. try { mixin(S_TRACE);
  1337. bool sameSc = _summ.id == node.attr("summId", false);
  1338. bool topLevel = node.attr!bool("topLevel", false, false);
  1339. if (node.name == BeastCard.XML_NAME_M) { mixin(S_TRACE);
  1340. auto bNode = node.child(BeastCard.XML_NAME, false);
  1341. if (!bNode.valid) return;
  1342. storeEdit(_motions.getSelectionIndex());
  1343. if (m.beast) _comm.delBeast.call(m.beast);
  1344. m.beast = null;
  1345. auto ver = new XMLInfo(_prop.sys, LATEST_VERSION);
  1346. auto bid = m.setBeastFromNode(bNode, ver);
  1347. if (bid && sameSc && topLevel && _prop.var.etc.linkCard) { mixin(S_TRACE);
  1348. m.beast = new BeastCard(1UL, "", "", "");
  1349. m.beast.linkId = bid;
  1350. }
  1351. resetMaxNest(m);
  1352. _beastImg.redraw();
  1353. foreach (dlg; modEvent) dlg();
  1354. refEnabled();
  1355. }
  1356. } catch (Exception e) {
  1357. debugln(e);
  1358. }
  1359. }
  1360. }
  1361. private void resetMaxNest(Motion m) { mixin(S_TRACE);
  1362. if (!m.beast || 0 == m.beast.linkId) { mixin(S_TRACE);
  1363. m.maxNest = Motion.maxNest_init;
  1364. _maxNest.setSelection(m.maxNest);
  1365. }
  1366. }
  1367. private class BeastTCPD : TCPD {
  1368. private bool __copy() { mixin(S_TRACE);
  1369. auto m = selection;
  1370. if (m) { mixin(S_TRACE);
  1371. assert (m.detail.use(MArg.BEAST));
  1372. if (m.beast) { mixin(S_TRACE);
  1373. auto node = XNode.create(BeastCard.XML_NAME_M);
  1374. node.newAttr("summId", _summ.id);
  1375. node.newAttr("paneId", "");
  1376. node.newAttr("scenarioPath", nabs(_summ.scenarioPath));
  1377. m.beast.toNode(node, new XMLOption(_prop.sys));
  1378. XMLtoCB(_prop, _comm.clipboard, node.text);
  1379. _comm.refreshToolBar();
  1380. return true;
  1381. }
  1382. }
  1383. return false;
  1384. }
  1385. override void cut(SelectionEvent se) { mixin(S_TRACE);
  1386. if (__copy()) { mixin(S_TRACE);
  1387. del(se);
  1388. }
  1389. }
  1390. override void copy(SelectionEvent se) { mixin(S_TRACE);
  1391. __copy();
  1392. }
  1393. override void paste(SelectionEvent se) { mixin(S_TRACE);
  1394. auto xml = CBtoXML(_comm.clipboard);
  1395. if (xml) { mixin(S_TRACE);
  1396. try { mixin(S_TRACE);
  1397. auto node = XNode.parse(xml);
  1398. pasteBeast(node);
  1399. _comm.refreshToolBar();
  1400. } catch {}
  1401. }
  1402. }
  1403. override void del(SelectionEvent se) { mixin(S_TRACE);
  1404. auto m = selection;
  1405. if (m) { mixin(S_TRACE);
  1406. assert (m.detail.use(MArg.BEAST));
  1407. if (m.beast) { mixin(S_TRACE);
  1408. storeEdit(_motions.getSelectionIndex());
  1409. if (m.beast) _comm.delBeast.call(m.beast);
  1410. m.beast = null;
  1411. resetMaxNest(m);
  1412. _beastImg.redraw();
  1413. foreach (dlg; modEvent) dlg();
  1414. _comm.refreshToolBar();
  1415. refEnabled();
  1416. }
  1417. }
  1418. }
  1419. override void clone(SelectionEvent se) { mixin(S_TRACE);
  1420. _comm.clipboard.memoryMode = true;
  1421. scope (exit) _comm.clipboard.memoryMode = false;
  1422. copy(se);
  1423. paste(se);
  1424. }
  1425. @property
  1426. override bool canDoTCPD() { mixin(S_TRACE);
  1427. return _beastImg.isFocusControl();
  1428. }
  1429. @property
  1430. override bool canDoT() { mixin(S_TRACE);
  1431. return !_readOnly && selection !is null;
  1432. }
  1433. @property
  1434. override bool canDoC() { mixin(S_TRACE);
  1435. return selection !is null;
  1436. }
  1437. @property
  1438. override bool canDoP() { mixin(S_TRACE);
  1439. return !_readOnly && CBisXML(_comm.clipboard);
  1440. }
  1441. @property
  1442. override bool canDoD() { mixin(S_TRACE);
  1443. return !_readOnly && selection !is null;
  1444. }
  1445. @property
  1446. override bool canDoClone() { mixin(S_TRACE);
  1447. return false;
  1448. }
  1449. }
  1450. void undo() { mixin(S_TRACE);
  1451. _undo.undo();
  1452. }
  1453. void redo() { mixin(S_TRACE);
  1454. _undo.redo();
  1455. }
  1456. bool openCWXPath(string path, bool shellActivate) { mixin(S_TRACE);
  1457. auto cate = cpcategory(path);
  1458. if (cate == "motion") { mixin(S_TRACE);
  1459. auto index = cpindex(path);
  1460. if (index >= _motions.getItemCount()) return false;
  1461. _motions.select(index);
  1462. refreshSels();
  1463. path = cpbottom(path);
  1464. if (!cphasattr(path, "nofocus")) .forceFocus(_motions, shellActivate);
  1465. if (cpempty(path)) { mixin(S_TRACE);
  1466. _comm.refreshToolBar();
  1467. return true;
  1468. }
  1469. auto m = selection;
  1470. if (m.beast) { mixin(S_TRACE);
  1471. switch (cpcategory(path)) {
  1472. case "beastcard":
  1473. if (0 != cpindex(path)) return false;
  1474. break;
  1475. case "beastcard:id":
  1476. if (m.beast.id != cpindex(path)) return false;
  1477. break;
  1478. default: return false;
  1479. }
  1480. path = cpbottom(path);
  1481. if ("event" == cpcategory(path)) { mixin(S_TRACE);
  1482. auto w = openBeastEventWin(m.beast);
  1483. if (!w) return false;
  1484. _comm.refreshToolBar();
  1485. return w.openCWXPath(path, shellActivate);
  1486. } else { mixin(S_TRACE);
  1487. if (cphasattr(path, "opendialog")) { mixin(S_TRACE);
  1488. auto d = editBeast();
  1489. if (!d) return false;
  1490. return d.openCWXPath(path, shellActivate);
  1491. }
  1492. _comm.refreshToolBar();
  1493. return true;
  1494. }
  1495. }
  1496. return false;
  1497. }
  1498. return cpempty(path);
  1499. }
  1500. }