PageRenderTime 71ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

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

https://bitbucket.org/k4nagatsuki/cwxeditor
D | 3121 lines | 3052 code | 58 blank | 11 comment | 478 complexity | 63095cde6e618b1a5cbda9fc2155e05c MD5 | raw file
Possible License(s): LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. module cwx.editor.gui.dwt.areatable;
  2. import cwx.flag;
  3. import cwx.area;
  4. import cwx.event;
  5. import cwx.utils;
  6. import cwx.summary;
  7. import cwx.background;
  8. import cwx.usecounter;
  9. import cwx.xml;
  10. import cwx.skin;
  11. import cwx.path;
  12. import cwx.structs;
  13. import cwx.menu;
  14. import cwx.types;
  15. import cwx.card;
  16. import cwx.system;
  17. import cwx.editor.gui.dwt.smalldialogs;
  18. import cwx.editor.gui.dwt.dprops;
  19. import cwx.editor.gui.dwt.dutils;
  20. import cwx.editor.gui.dwt.dskin;
  21. import cwx.editor.gui.dwt.flagtable;
  22. import cwx.editor.gui.dwt.areaview;
  23. import cwx.editor.gui.dwt.areawindow;
  24. import cwx.editor.gui.dwt.eventwindow;
  25. import cwx.editor.gui.dwt.summarydialog;
  26. import cwx.editor.gui.dwt.commons;
  27. import cwx.editor.gui.dwt.properties;
  28. import cwx.editor.gui.dwt.xmlbytestransfer;
  29. import cwx.editor.gui.dwt.undo;
  30. import cwx.editor.gui.dwt.dmenu;
  31. import cwx.editor.gui.dwt.customtable;
  32. import cwx.editor.gui.dwt.incsearch;
  33. import cwx.editor.gui.dwt.splitpane;
  34. import cwx.editor.gui.dwt.centerlayout;
  35. import std.algorithm : max, min;
  36. import std.array : split;
  37. import std.conv;
  38. import std.string : icmp, join, toLower;
  39. import org.eclipse.swt.all;
  40. import java.lang.all;
  41. /// ??????????????????????
  42. class AreaTable : TCPD {
  43. private:
  44. int compType(const Object o1, const Object o2) { mixin(S_TRACE);
  45. if (cast(const Summary) o1) return -1;
  46. if (cast(const Summary) o2) return 1;
  47. if (cast(const Area) o1) { mixin(S_TRACE);
  48. if (cast(const Battle) o2) return -1;
  49. if (cast(const Package) o2) return -1;
  50. }
  51. if (cast(const Battle) o1) { mixin(S_TRACE);
  52. if (cast(const Area) o2) return 1;
  53. if (cast(const Package) o2) return -1;
  54. }
  55. if (cast(const Package) o1) { mixin(S_TRACE);
  56. if (cast(const Area) o2) return 1;
  57. if (cast(const Battle) o2) return 1;
  58. }
  59. return 0;
  60. }
  61. bool compID(const Object o1, const Object o2) { mixin(S_TRACE);
  62. auto c = compType(o1, o2);
  63. if (c == 0) { mixin(S_TRACE);
  64. auto a1 = cast(const AbstractArea) o1;
  65. auto a2 = cast(const AbstractArea) o2;
  66. if (a1.id < a2.id) return true;
  67. if (a1.id > a2.id) return false;
  68. return false;
  69. }
  70. return c < 0;
  71. }
  72. bool compName(const Object o1, const Object o2) { mixin(S_TRACE);
  73. auto c = compType(o1, o2);
  74. if (c == 0) { mixin(S_TRACE);
  75. auto a1 = cast(const AbstractArea) o1;
  76. auto a2 = cast(const AbstractArea) o2;
  77. if (_prop.var.etc.logicalSort) { mixin(S_TRACE);
  78. c = incmp(a1.name, a2.name);
  79. } else { mixin(S_TRACE);
  80. c = icmp(a1.name, a2.name);
  81. }
  82. if (c == 0) return compID(o1, o2);
  83. }
  84. return c < 0;
  85. }
  86. bool compUC(const Object o1, const Object o2) { mixin(S_TRACE);
  87. auto c = compType(o1, o2);
  88. if (c == 0) { mixin(S_TRACE);
  89. int uc1 = 0;
  90. int uc2 = 0;
  91. auto a1 = cast(const Area) o1;
  92. auto a2 = cast(const Area) o2;
  93. if (a1 && a2) { mixin(S_TRACE);
  94. uc1 = _summ.useCounter.get(toAreaId(a1.id));
  95. uc2 = _summ.useCounter.get(toAreaId(a2.id));
  96. }
  97. auto b1 = cast(const Battle) o1;
  98. auto b2 = cast(const Battle) o2;
  99. if (b1 && b2) { mixin(S_TRACE);
  100. uc1 = _summ.useCounter.get(toBattleId(b1.id));
  101. uc2 = _summ.useCounter.get(toBattleId(b2.id));
  102. }
  103. auto p1 = cast(const Package) o1;
  104. auto p2 = cast(const Package) o2;
  105. if (p1 && p2) { mixin(S_TRACE);
  106. uc1 = _summ.useCounter.get(toPackageId(p1.id));
  107. uc2 = _summ.useCounter.get(toPackageId(p2.id));
  108. }
  109. if (uc1 < uc2) return true;
  110. if (uc1 > uc2) return false;
  111. return compID(o1, o2);
  112. }
  113. return c < 0;
  114. }
  115. bool revCompID(const Object o1, const Object o2) { mixin(S_TRACE);
  116. auto c = compType(o2, o1);
  117. if (c == 0) { mixin(S_TRACE);
  118. auto a1 = cast(const AbstractArea) o2;
  119. auto a2 = cast(const AbstractArea) o1;
  120. if (a1.id < a2.id) return true;
  121. if (a1.id > a2.id) return false;
  122. return false;
  123. }
  124. return 0 < c;
  125. }
  126. bool revCompName(const Object o1, const Object o2) { mixin(S_TRACE);
  127. auto c = compType(o2, o1);
  128. if (c == 0) { mixin(S_TRACE);
  129. auto a1 = cast(const AbstractArea) o2;
  130. auto a2 = cast(const AbstractArea) o1;
  131. if (_prop.var.etc.logicalSort) { mixin(S_TRACE);
  132. c = incmp(a2.name, a1.name);
  133. } else { mixin(S_TRACE);
  134. c = icmp(a2.name, a1.name);
  135. }
  136. if (c == 0) return revCompID(o1, o2);
  137. }
  138. return 0 < c;
  139. }
  140. bool revCompUC(const Object o1, const Object o2) { mixin(S_TRACE);
  141. auto c = compType(o2, o1);
  142. if (c == 0) { mixin(S_TRACE);
  143. int uc1 = 0;
  144. int uc2 = 0;
  145. auto a1 = cast(const Area) o2;
  146. auto a2 = cast(const Area) o1;
  147. if (a1 && a2) { mixin(S_TRACE);
  148. uc1 = _summ.useCounter.get(toAreaId(a1.id));
  149. uc2 = _summ.useCounter.get(toAreaId(a2.id));
  150. }
  151. auto b1 = cast(const Battle) o2;
  152. auto b2 = cast(const Battle) o1;
  153. if (b1 && b2) { mixin(S_TRACE);
  154. uc1 = _summ.useCounter.get(toBattleId(b1.id));
  155. uc2 = _summ.useCounter.get(toBattleId(b2.id));
  156. }
  157. auto p1 = cast(const Package) o2;
  158. auto p2 = cast(const Package) o1;
  159. if (p1 && p2) { mixin(S_TRACE);
  160. uc1 = _summ.useCounter.get(toPackageId(p1.id));
  161. uc2 = _summ.useCounter.get(toPackageId(p2.id));
  162. }
  163. if (uc1 < uc2) return true;
  164. if (uc1 > uc2) return false;
  165. return revCompID(o1, o2);
  166. }
  167. return 0 < c;
  168. }
  169. private static void saveIDs(Summary summ, out ulong[] areaIDs, out ulong[] battleIDs, out ulong[] packageIDs) { mixin(S_TRACE);
  170. areaIDs.length = 0;
  171. foreach (a; summ.areas) areaIDs ~= a.id;
  172. battleIDs.length = 0;
  173. foreach (a; summ.battles) battleIDs ~= a.id;
  174. packageIDs.length = 0;
  175. foreach (a; summ.packages) packageIDs ~= a.id;
  176. }
  177. static class ATUndo : Undo {
  178. protected AreaTable _v = null;
  179. protected Commons comm;
  180. protected Summary summ;
  181. protected bool one = true;
  182. protected AbstractArea[] calls, delCalls;
  183. private ulong[] _areaIDs;
  184. private ulong[] _areaIDsB;
  185. private ulong[] _battleIDs;
  186. private ulong[] _battleIDsB;
  187. private ulong[] _packageIDs;
  188. private ulong[] _packageIDsB;
  189. private ulong _sel;
  190. private TypeInfo _selType;
  191. private ulong _selB;
  192. private TypeInfo _selTypeB;
  193. private DirTree _dirs, _dirsB;
  194. this (AreaTable v, Commons comm, Summary summ) { mixin(S_TRACE);
  195. _v = v;
  196. this.comm = comm;
  197. this.summ = summ;
  198. saveIDs(v);
  199. }
  200. private void saveIDs(AreaTable v) { mixin(S_TRACE);
  201. AreaTable.saveIDs(summ, _areaIDs, _battleIDs, _packageIDs);
  202. if (v && v._areas && !v._areas.isDisposed()) { mixin(S_TRACE);
  203. v.getSelectionInfo(_sel, _selType);
  204. }
  205. if (v) {
  206. _dirs = v._dirs.dup;
  207. }
  208. }
  209. abstract override void undo();
  210. abstract override void redo();
  211. abstract override void dispose();
  212. protected void udb(AreaTable v) { mixin(S_TRACE);
  213. _areaIDsB = _areaIDs.dup;
  214. _battleIDsB = _battleIDs.dup;
  215. _packageIDsB = _packageIDs.dup;
  216. _selB = _sel;
  217. _selTypeB = _selType;
  218. _dirsB = _dirs;
  219. saveIDs(v);
  220. if (!one) return;
  221. if (v && v._areas && !v._areas.isDisposed()) { mixin(S_TRACE);
  222. .forceFocus(v._areas, false);
  223. }
  224. if (v._parent) v._parent.setRedraw(false);
  225. }
  226. private void resetID(alias ToID, A)(AreaTable v, A[] arr, ulong[] ids) { mixin(S_TRACE);
  227. ulong[] oldIDs;
  228. foreach (i, a; arr) { mixin(S_TRACE);
  229. auto oID = a.id;
  230. a.id = ulong.max - arr.length + i;
  231. summ.useCounter.change(ToID(oID), ToID(a.id));
  232. oldIDs ~= oID;
  233. }
  234. foreach (i, a; arr) { mixin(S_TRACE);
  235. auto oID = a.id;
  236. a.id = ids[i];
  237. summ.useCounter.change(ToID(oID), ToID(a.id));
  238. }
  239. foreach (i, a; arr) { mixin(S_TRACE);
  240. if (a.id != oldIDs[i] || calls.contains(a)) { mixin(S_TRACE);
  241. staticCallRefArea(v, comm, a);
  242. }
  243. }
  244. }
  245. protected ulong uid(ulong id, TypeInfo type) { mixin(S_TRACE);
  246. return id;
  247. }
  248. protected void uda(AreaTable v) { mixin(S_TRACE);
  249. resetID!toAreaId(v, summ.areas, _areaIDsB);
  250. resetID!toBattleId(v, summ.battles, _battleIDsB);
  251. resetID!toPackageId(v, summ.packages, _packageIDsB);
  252. foreach (area; delCalls) {
  253. auto a = cast(Area) area;
  254. if (a) { mixin(S_TRACE);
  255. comm.delArea.call(v, a);
  256. }
  257. auto b = cast(Battle) area;
  258. if (b) { mixin(S_TRACE);
  259. comm.delBattle.call(v, b);
  260. }
  261. auto p = cast(Package) area;
  262. if (p) { mixin(S_TRACE);
  263. comm.delPackage.call(v, p);
  264. }
  265. }
  266. calls = [];
  267. delCalls = [];
  268. if (!one) return;
  269. if (v) { mixin(S_TRACE);
  270. v._dirs = _dirsB.dup;
  271. v.refreshDirTree();
  272. }
  273. if (v && v._areas && !v._areas.isDisposed()) { mixin(S_TRACE);
  274. v.refreshAreas();
  275. v.selectFromInfo(_selB, _selTypeB);
  276. v.refreshStatusLine();
  277. }
  278. comm.refUseCount.call();
  279. comm.refreshToolBar();
  280. if (v._parent) v._parent.setRedraw(true);
  281. }
  282. protected AreaTable view() { mixin(S_TRACE);
  283. return _v;
  284. }
  285. }
  286. static class ATUndoArr : Undo {
  287. private ATUndo[] _array;
  288. this (ATUndo[] array) { mixin(S_TRACE);
  289. _array = array;
  290. }
  291. void undo() { mixin(S_TRACE);
  292. foreach_reverse (i, u; _array) { mixin(S_TRACE);
  293. u.one = (i == 0);
  294. u.undo();
  295. }
  296. }
  297. void redo() { mixin(S_TRACE);
  298. foreach (i, u; _array) { mixin(S_TRACE);
  299. u.one = (i + 1 == _array.length);
  300. u.redo();
  301. }
  302. }
  303. void dispose() { mixin(S_TRACE);
  304. foreach (u; _array) u.dispose();
  305. }
  306. }
  307. void storeEmpty() { mixin(S_TRACE);
  308. _undo ~= new UndoIDs(this, _comm, _summ);
  309. }
  310. static class UndoIDs : ATUndo {
  311. this (AreaTable v, Commons comm, Summary summ) { mixin(S_TRACE);
  312. super (v, comm, summ);
  313. }
  314. override void undo() { mixin(S_TRACE);
  315. auto v = view();
  316. udb(v);
  317. scope (exit) uda(v);
  318. }
  319. override void redo() { mixin(S_TRACE);
  320. auto v = view();
  321. udb(v);
  322. scope (exit) uda(v);
  323. }
  324. override void dispose() {}
  325. }
  326. static class UndoEdit : ATUndo {
  327. private string _name;
  328. private ulong _id;
  329. private TypeInfo _type;
  330. static struct SummData {
  331. string scenarioName;
  332. string imagePath;
  333. string author;
  334. int levelMin, levelMax;
  335. string desc;
  336. string type;
  337. string[] rCoupons;
  338. uint rCouponNum;
  339. ulong startArea;
  340. Skin skin;
  341. this (Commons comm, Summary summ) { mixin(S_TRACE);
  342. scenarioName = summ.scenarioName;
  343. imagePath = summ.imagePath;
  344. author = summ.author;
  345. levelMin = summ.levelMin;
  346. levelMax = summ.levelMax;
  347. desc = summ.desc;
  348. type = summ.type;
  349. rCoupons = summ.rCoupons.dup;
  350. rCouponNum = summ.rCouponNum;
  351. startArea = summ.startArea;
  352. skin = comm.skin;
  353. }
  354. void toSummary(Commons comm, Summary summ) { mixin(S_TRACE);
  355. summ.scenarioName = scenarioName;
  356. summ.imagePath = imagePath;
  357. summ.author = author;
  358. summ.levelMin = levelMin;
  359. summ.levelMax = levelMax;
  360. summ.desc = desc;
  361. summ.type = type;
  362. summ.rCoupons = rCoupons;
  363. summ.rCouponNum = rCouponNum;
  364. summ.startArea = startArea;
  365. comm.skin = skin;
  366. }
  367. }
  368. private SummData _summData;
  369. this (AreaTable v, Commons comm, Summary summ, ulong id, TypeInfo type) { mixin(S_TRACE);
  370. super (v, comm, summ);
  371. if (0 == id) { mixin(S_TRACE);
  372. _summData = SummData(comm, summ);
  373. } else { mixin(S_TRACE);
  374. _name = areaFromInfo(summ, id, type).name;
  375. }
  376. _id = id;
  377. _type = type;
  378. }
  379. private void impl() { mixin(S_TRACE);
  380. auto v = view();
  381. udb(v);
  382. scope (exit) uda(v);
  383. if (0 == _id) { mixin(S_TRACE);
  384. auto oldData = SummData(comm, summ);
  385. bool refSkin = oldData.skin !is _summData.skin;
  386. _summData.toSummary(comm, summ);
  387. _summData = oldData;
  388. if (v && v._areas && !v._areas.isDisposed()) { mixin(S_TRACE);
  389. auto itm = v.getItemFrom(uid(_id, _type), _type);
  390. if (itm) itm.setText(NAME, summ.scenarioName);
  391. }
  392. comm.refScenarioName.call(v);
  393. if (refSkin) comm.refSkin.call();
  394. } else { mixin(S_TRACE);
  395. auto area = areaFromInfo(summ, uid(_id, _type), _type);
  396. string oldName = area.name;
  397. area.name = _name;
  398. _name = oldName;
  399. if (v && v._areas && !v._areas.isDisposed()) { mixin(S_TRACE);
  400. auto itm = v.getItemFrom(uid(_id, _type), _type);
  401. if (itm) itm.setText(NAME, area.name);
  402. }
  403. calls ~= area;
  404. }
  405. comm.refUseCount.call();
  406. }
  407. override void undo() { mixin(S_TRACE);
  408. impl();
  409. }
  410. override void redo() { mixin(S_TRACE);
  411. impl();
  412. }
  413. override void dispose() {}
  414. }
  415. void storeEdit(int index) { mixin(S_TRACE);
  416. ulong id;
  417. TypeInfo type;
  418. getInfo(index, id, type);
  419. storeEdit(id, type);
  420. }
  421. void storeEdit(ulong id, TypeInfo type) { mixin(S_TRACE);
  422. _undo ~= new UndoEdit(this, _comm, _summ, id, type);
  423. }
  424. static class UndoMove : ATUndo {
  425. private int _removeIndex, _insertIndex;
  426. private TypeInfo _type;
  427. this (AreaTable v, Commons comm, Summary summ, int removeIndex, int insertIndex, TypeInfo type) { mixin(S_TRACE);
  428. super (v, comm, summ);
  429. _removeIndex = removeIndex;
  430. _insertIndex = insertIndex;
  431. if (_removeIndex < _insertIndex) _insertIndex--;
  432. _type = type;
  433. }
  434. private void impl() { mixin(S_TRACE);
  435. auto v = view();
  436. udb(v);
  437. scope (exit) uda(v);
  438. int removeIndex = _removeIndex;
  439. int insertIndex = _insertIndex;
  440. if (insertIndex < removeIndex) removeIndex++;
  441. if (_type is typeid(Area)) { mixin(S_TRACE);
  442. auto a = summ.areas[insertIndex];
  443. summ.insert(removeIndex, a);
  444. } else if (_type is typeid(Battle)) { mixin(S_TRACE);
  445. auto a = summ.battles[insertIndex];
  446. summ.insert(removeIndex, a);
  447. } else if (_type is typeid(Package)) { mixin(S_TRACE);
  448. auto a = summ.packages[insertIndex];
  449. summ.insert(removeIndex, a);
  450. }
  451. std.algorithm.swap(_removeIndex, _insertIndex);
  452. }
  453. override void undo() { mixin(S_TRACE);
  454. impl();
  455. }
  456. override void redo() { mixin(S_TRACE);
  457. impl();
  458. }
  459. override void dispose() {}
  460. }
  461. void storeMove(int removeIndex, int insertIndex, TypeInfo type) { mixin(S_TRACE);
  462. assert (_areas.getSortColumn() is null || _areas.getSortColumn() is _idSorter.column);
  463. _undo ~= new UndoMove(this, _comm, _summ, removeIndex, insertIndex, type);
  464. }
  465. static class UndoSwap : ATUndo {
  466. private int _index1, _index2;
  467. this (AreaTable v, Commons comm, Summary summ, int index1, int index2) { mixin(S_TRACE);
  468. super (v, comm, summ);
  469. _index1 = index1;
  470. _index2 = index2;
  471. }
  472. private void impl() { mixin(S_TRACE);
  473. auto v = view();
  474. udb(v);
  475. scope (exit) uda(v);
  476. auto area1 = areaFromIndex(summ, _index1);
  477. auto area2 = areaFromIndex(summ, _index2);
  478. auto a = cast(Area) area1;
  479. if (a) { mixin(S_TRACE);
  480. summ.swap!Area(toAreaIndex(summ, _index1), toAreaIndex(summ, _index2));
  481. }
  482. auto b = cast(Battle) area1;
  483. if (b) { mixin(S_TRACE);
  484. summ.swap!Battle(toBattleIndex(summ, _index1), toBattleIndex(summ, _index2));
  485. }
  486. auto p = cast(Package) area1;
  487. if (p) { mixin(S_TRACE);
  488. summ.swap!Package(toPackageIndex(summ, _index1), toPackageIndex(summ, _index2));
  489. }
  490. calls ~= area1;
  491. calls ~= area2;
  492. std.algorithm.swap(_index1, _index2);
  493. }
  494. override void undo() { mixin(S_TRACE);
  495. impl();
  496. }
  497. override void redo() { mixin(S_TRACE);
  498. impl();
  499. }
  500. override void dispose() {}
  501. }
  502. void storeSwap(int index1, int index2) { mixin(S_TRACE);
  503. assert (_areas.getSortColumn() is null || _areas.getSortColumn() is _idSorter.column);
  504. _undo ~= new UndoSwap(this, _comm, _summ, index1, index2);
  505. }
  506. static class UndoInsertDelete : ATUndo {
  507. private bool _insert;
  508. private ulong _id;
  509. private TypeInfo _type;
  510. private AbstractArea _area = null;
  511. private bool _isStartArea = false;
  512. private int _delIndex = -1;
  513. this (AreaTable v, Commons comm, Summary summ, ulong id, TypeInfo type, bool insert, ulong[] a, ulong[] b, ulong[] p) { mixin(S_TRACE);
  514. super (v, comm, summ);
  515. _insert = insert;
  516. _id = id;
  517. _type = type;
  518. if (insert) { mixin(S_TRACE);
  519. _areaIDs = a;
  520. _battleIDs = b;
  521. _packageIDs = p;
  522. } else { mixin(S_TRACE);
  523. initUndoDelete();
  524. }
  525. }
  526. private void initUndoDelete() { mixin(S_TRACE);
  527. auto area = areaFromInfo(summ, uid(_id, _type), _type);
  528. _delIndex = toIndexFrom(summ, uid(_id, _type), _type);
  529. _isStartArea = cast(Area) area && summ.startArea == area.id;
  530. _area = area.dup;
  531. _area.setUseCounter(summ.useCounter.sub);
  532. }
  533. private void undoInsert() { mixin(S_TRACE);
  534. auto v = view();
  535. udb(v);
  536. scope (exit) uda(v);
  537. _insert = false;
  538. initUndoDelete();
  539. if (v && v._areas && !v._areas.isDisposed()) { mixin(S_TRACE);
  540. auto itm = v.getItemFrom(uid(_id, _type), _type);
  541. if (itm) itm.dispose();
  542. }
  543. auto area = areaFromInfo(summ, uid(_id, _type), _type);
  544. delCalls ~= area;
  545. summ.remove(area);
  546. comm.refUseCount.call();
  547. }
  548. void undoDelete() { mixin(S_TRACE);
  549. auto v = view();
  550. udb(v);
  551. scope (exit) uda(v);
  552. scope (exit) _area = null;
  553. _insert = true;
  554. _area.removeUseCounter();
  555. auto a = cast(Area) _area;
  556. calls ~= _area;
  557. if (a) { mixin(S_TRACE);
  558. summ.insert(_delIndex, a);
  559. if (v && v._areas && !v._areas.isDisposed()) v.refreshAreas();
  560. if (_isStartArea) { mixin(S_TRACE);
  561. summ.startArea = a.id;
  562. _isStartArea = false;
  563. }
  564. return;
  565. }
  566. auto b = cast(Battle) _area;
  567. if (b) { mixin(S_TRACE);
  568. summ.insert(_delIndex, b);
  569. if (v && v._areas && !v._areas.isDisposed()) v.refreshAreas();
  570. return;
  571. }
  572. auto p = cast(Package) _area;
  573. if (p) { mixin(S_TRACE);
  574. summ.insert(_delIndex, p);
  575. if (v && v._areas && !v._areas.isDisposed()) v.refreshAreas();
  576. return;
  577. }
  578. assert (0);
  579. }
  580. override void undo() { mixin(S_TRACE);
  581. if (_insert) { mixin(S_TRACE);
  582. undoInsert();
  583. } else { mixin(S_TRACE);
  584. undoDelete();
  585. }
  586. }
  587. override void redo() { mixin(S_TRACE);
  588. undo();
  589. }
  590. override void dispose() { mixin(S_TRACE);
  591. if (_area) { mixin(S_TRACE);
  592. _area.removeUseCounter();
  593. }
  594. }
  595. }
  596. void storeInsert(ulong id, TypeInfo type, ulong[] a, ulong[] b, ulong[] p) { mixin(S_TRACE);
  597. _undo ~= new UndoInsertDelete(this, _comm, _summ, id, type, true, a, b, p);
  598. }
  599. void storeDelete(int index) { mixin(S_TRACE);
  600. ulong id;
  601. TypeInfo type;
  602. getInfo(index, id, type);
  603. _undo ~= new UndoInsertDelete(this, _comm, _summ, id, type, false, [], [], []);
  604. }
  605. static class UndoRenameDir : ATUndo {
  606. private string _oldPath, _newPath;
  607. this (AreaTable v, Commons comm, Summary summ, string oldPath, string newPath) { mixin(S_TRACE);
  608. super (v, comm, summ);
  609. _oldPath = oldPath;
  610. _newPath = newPath;
  611. }
  612. private void impl() { mixin(S_TRACE);
  613. auto v = view();
  614. udb(v);
  615. scope (exit) uda(v);
  616. void put(AbstractArea area) { mixin(S_TRACE);
  617. if (area.dirName == _newPath) { mixin(S_TRACE);
  618. area.dirName = _oldPath;
  619. calls ~= area;
  620. }
  621. }
  622. foreach (a; summ.areas) put(a);
  623. foreach (a; summ.battles) put(a);
  624. foreach (a; summ.packages) put(a);
  625. std.algorithm.swap(_oldPath, _newPath);
  626. if (v && v._areas && !v._areas.isDisposed()) {
  627. auto itm = v.findDirTree(_oldPath);
  628. auto dir = cast(DirTree)itm.getData();
  629. dir.name = .split(_newPath, "\\")[$ - 1];
  630. v._dir = dir.path;
  631. v.refreshAreas();
  632. }
  633. }
  634. override void undo() { mixin(S_TRACE);
  635. impl();
  636. }
  637. override void redo() { mixin(S_TRACE);
  638. impl();
  639. }
  640. override void dispose() {}
  641. }
  642. void storeRenameDir(string oldPath, string newPath) {
  643. _undo ~= new UndoRenameDir(this, _comm, _summ, oldPath, newPath);
  644. }
  645. void dirEditEnd(TreeItem itm, Control ctrl) { mixin(S_TRACE);
  646. if (_readOnly) return;
  647. assert (_dirMode);
  648. auto t = cast(Text)ctrl;
  649. if (!t) return;
  650. auto newText = std.array.replace(t.getText(), "\\", "");
  651. if (newText == "") return;
  652. if (itm.getText() == newText) return;
  653. if (auto summ = cast(Summary)itm.getData()) { mixin(S_TRACE);
  654. storeEdit(0UL, null);
  655. summ.scenarioName = newText;
  656. itm.setText(newText);
  657. _comm.refScenarioName.call();
  658. } else { mixin(S_TRACE);
  659. auto dir = cast(DirTree)itm.getData();
  660. auto oldPath = dir.path;
  661. dir.name = createNewName(newText, (s) {
  662. foreach (n; dir.parent.subDirs) {
  663. if (n is dir) continue;
  664. if (0 == icmp(n.name, s)) {
  665. return false;
  666. }
  667. }
  668. return true;
  669. });
  670. auto path = dir.path;
  671. itm.setText(dir.name);
  672. storeRenameDir(oldPath, path);
  673. void put(AbstractArea area) {
  674. if (area.dirName == oldPath) {
  675. area.dirName = path;
  676. callRefArea(area);
  677. }
  678. }
  679. foreach (a; _summ.areas) put(a);
  680. foreach (a; _summ.battles) put(a);
  681. foreach (a; _summ.packages) put(a);
  682. sortDirTree();
  683. refreshDirTree();
  684. updateDirSel();
  685. }
  686. _comm.refreshToolBar();
  687. }
  688. void editEnd(TableItem itm, int column, string newText) { mixin(S_TRACE);
  689. if (_readOnly) return;
  690. assert (column == 1);
  691. if (!newText.length) return;
  692. if (auto summ = cast(Summary) itm.getData()) { mixin(S_TRACE);
  693. if (summ.scenarioName == newText) return;
  694. storeEdit(0UL, null);
  695. summ.scenarioName = newText;
  696. itm.setText(NAME, newText);
  697. _comm.refScenarioName.call();
  698. } else if (auto area = cast(AbstractArea) itm.getData()) { mixin(S_TRACE);
  699. assert (area !is null);
  700. if (_dirMode) { mixin(S_TRACE);
  701. newText = std.array.replace(newText, "\\", "");
  702. if (newText == "") return;
  703. if (area.baseName == newText) return;
  704. storeEdit(_areas.indexOf(itm));
  705. area.baseName = newText;
  706. } else { mixin(S_TRACE);
  707. if (area.name == newText) return;
  708. storeEdit(_areas.indexOf(itm));
  709. area.name = newText;
  710. }
  711. refreshAreas();
  712. callRefArea(area);
  713. }
  714. _comm.refreshToolBar();
  715. }
  716. private static const ID = 0;
  717. private static const NAME = 1;
  718. private static const UC = 2;
  719. int _readOnly = SWT.NONE;
  720. bool _dirMode = false;
  721. string _dir = "";
  722. Commons _comm;
  723. Props _prop;
  724. Composite _parent = null;
  725. FlagTable _flags = null;
  726. Summary _summ, _importTarget = null;
  727. TableSorter!Object _idSorter;
  728. TableSorter!Object _nameSorter;
  729. TableSorter!Object _ucSorter;
  730. Tree _dirTree = null;
  731. Table _areas;
  732. TableTextEdit _areasEdit;
  733. TreeEdit _areaDirEdit = null;
  734. DirTree _dirs = null;
  735. IncSearch _incSearch = null;
  736. private void incSearch() { mixin(S_TRACE);
  737. .forceFocus(_areas, true);
  738. _incSearch.startIncSearch();
  739. }
  740. UndoManager _undo;
  741. string _statusLine = "";
  742. void refreshStatusLine() { mixin(S_TRACE);
  743. string s = "";
  744. void put(lazy string name, size_t count) { mixin(S_TRACE);
  745. if (!count) return;
  746. if (s.length) s ~= " ";
  747. s ~= .tryFormat(_prop.msgs.areaStatus, name, count);
  748. }
  749. if (_summ) { mixin(S_TRACE);
  750. put(_prop.msgs.area, areaCount);
  751. put(_prop.msgs.battle, battleCount);
  752. put(_prop.msgs.cwPackage, packageCount);
  753. }
  754. _statusLine = s;
  755. _comm.setStatusLine(_areas, _statusLine);
  756. }
  757. size_t count(A)(A[] areas) { mixin(S_TRACE);
  758. if (_dirMode) { mixin(S_TRACE);
  759. size_t n = 0;
  760. foreach (a; areas) { mixin(S_TRACE);
  761. if (0 == icmp(a.dirName, _dir)) n++;
  762. }
  763. return n;
  764. } else { mixin(S_TRACE);
  765. return areas.length;
  766. }
  767. }
  768. @property
  769. size_t areaCount() { return count(_summ.areas); }
  770. @property
  771. size_t battleCount() { return count(_summ.battles); }
  772. @property
  773. size_t packageCount() { return count(_summ.packages); }
  774. void getSelectionInfo(out ulong id, out TypeInfo type) { mixin(S_TRACE);
  775. getInfo(_areas.getSelectionIndex(), id, type);
  776. }
  777. void getInfo(int index, out ulong id, out TypeInfo type) { mixin(S_TRACE);
  778. id = 0;
  779. type = null;
  780. if (0 <= index) { mixin(S_TRACE);
  781. auto d = _areas.getItem(index).getData();
  782. auto a = cast(AbstractArea)d;
  783. if (a)getInfoFromArea(a, id, type);
  784. }
  785. }
  786. void getInfoFromArea(in AbstractArea d, out ulong id, out TypeInfo type) { mixin(S_TRACE);
  787. auto a = cast(Area) d;
  788. if (a) { mixin(S_TRACE);
  789. id = a.id;
  790. type = typeid(Area);
  791. }
  792. auto b = cast(Battle) d;
  793. if (b) { mixin(S_TRACE);
  794. id = b.id;
  795. type = typeid(Battle);
  796. }
  797. auto p = cast(Package) d;
  798. if (p) { mixin(S_TRACE);
  799. id = p.id;
  800. type = typeid(Package);
  801. }
  802. }
  803. void selectFromInfo(ulong id, in TypeInfo type) { mixin(S_TRACE);
  804. if (type is typeid(Area)) { mixin(S_TRACE);
  805. select(_summ.area(id));
  806. } else if (type is typeid(Battle)) { mixin(S_TRACE);
  807. select(_summ.battle(id));
  808. } else if (type is typeid(Package)) { mixin(S_TRACE);
  809. select(_summ.cwPackage(id));
  810. } else { mixin(S_TRACE);
  811. if (_dirMode) { mixin(S_TRACE);
  812. _dirTree.setSelection([_dirTree.getItem(0)]);
  813. } else { mixin(S_TRACE);
  814. if (_areas.getItemCount()) _areas.select(0);
  815. }
  816. }
  817. }
  818. static AbstractArea areaFromInfo(Summary summ, ulong id, TypeInfo type) { mixin(S_TRACE);
  819. if (type is typeid(Area)) { mixin(S_TRACE);
  820. return summ.area(id);
  821. } else if (type is typeid(Battle)) { mixin(S_TRACE);
  822. return summ.battle(id);
  823. } else if (type is typeid(Package)) { mixin(S_TRACE);
  824. return summ.cwPackage(id);
  825. } else assert (0);
  826. }
  827. TableItem getItemFrom(ulong id, TypeInfo type) { mixin(S_TRACE);
  828. if (type is typeid(Area)) { mixin(S_TRACE);
  829. foreach (itm; _areas.getItems()) { mixin(S_TRACE);
  830. if (cast(Area)itm.getData() && (cast(AbstractArea)itm.getData()).id == id) { mixin(S_TRACE);
  831. return itm;
  832. }
  833. }
  834. return null;
  835. } else if (type is typeid(Battle)) { mixin(S_TRACE);
  836. foreach (itm; _areas.getItems()) { mixin(S_TRACE);
  837. if (cast(Battle)itm.getData() && (cast(AbstractArea)itm.getData()).id == id) { mixin(S_TRACE);
  838. return itm;
  839. }
  840. }
  841. return null;
  842. } else if (type is typeid(Package)) { mixin(S_TRACE);
  843. foreach (itm; _areas.getItems()) { mixin(S_TRACE);
  844. if (cast(Package)itm.getData() && (cast(AbstractArea)itm.getData()).id == id) { mixin(S_TRACE);
  845. return itm;
  846. }
  847. }
  848. return null;
  849. }
  850. return showSummary ? _areas.getItem(0) : null;
  851. }
  852. static int toIndexFrom(Summary summ, ulong id, TypeInfo type) { mixin(S_TRACE);
  853. if (type is typeid(Area)) { mixin(S_TRACE);
  854. foreach (i, a; summ.areas) { mixin(S_TRACE);
  855. if (a.id == id) return i;
  856. }
  857. } else if (type is typeid(Battle)) { mixin(S_TRACE);
  858. foreach (i, a; summ.battles) { mixin(S_TRACE);
  859. if (a.id == id) return i;
  860. }
  861. } else if (type is typeid(Package)) { mixin(S_TRACE);
  862. foreach (i, a; summ.packages) { mixin(S_TRACE);
  863. if (a.id == id) return i;
  864. }
  865. } else assert (0);
  866. return -1;
  867. }
  868. static int indexFrom(A)(Summary summ, int index) { mixin(S_TRACE);
  869. static if (is(A : Area)) {
  870. return index;
  871. } else static if (is(A : Battle)) {
  872. return index + summ.areas.length;
  873. } else static if (is(A : Package)) {
  874. return index + summ.areas.length + summ.battles.length;
  875. } else static assert (0);
  876. }
  877. static int toIndex(A)(Summary summ, int index) { mixin(S_TRACE);
  878. static if (is(A : Area)) {
  879. return index;
  880. } else static if (is(A : Battle)) {
  881. return index - summ.areas.length;
  882. } else static if (is(A : Package)) {
  883. return index - (summ.areas.length + summ.battles.length);
  884. } else static assert (0);
  885. }
  886. alias toIndex!Area toAreaIndex;
  887. alias toIndex!Battle toBattleIndex;
  888. alias toIndex!Package toPackageIndex;
  889. static AbstractArea areaFromIndex(Summary summ, int index) { mixin(S_TRACE);
  890. if (summ.areas.length + summ.battles.length <= index) { mixin(S_TRACE);
  891. return summ.packages[toPackageIndex(summ, index)];
  892. }
  893. if (summ.areas.length <= index) { mixin(S_TRACE);
  894. return summ.battles[toBattleIndex(summ, index)];
  895. }
  896. if (0 <= index) { mixin(S_TRACE);
  897. return summ.areas[toAreaIndex(summ, index)];
  898. }
  899. return null;
  900. }
  901. AbstractArea getSelectionArea() { mixin(S_TRACE);
  902. auto i = _areas.getSelectionIndex();
  903. if (0 <= i) { mixin(S_TRACE);
  904. return cast(AbstractArea) _areas.getItem(i).getData();
  905. }
  906. return null;
  907. }
  908. AbstractArea[] getSelectionAreas() { mixin(S_TRACE);
  909. AbstractArea[] areas;
  910. foreach (itm; _areas.getSelection()) { mixin(S_TRACE);
  911. if (auto a = cast(AbstractArea)itm.getData()) { mixin(S_TRACE);
  912. areas ~= a;
  913. }
  914. }
  915. return areas;
  916. }
  917. void refArea(Object sender, Area a) { mixin(S_TRACE);
  918. if (_readOnly) return;
  919. if (sender is this) return;
  920. foreach (itm; _areas.getItems()) { mixin(S_TRACE);
  921. if (itm.getData() is a) refData(a, itm);
  922. }
  923. }
  924. void refBattle(Object sender, Battle a) { mixin(S_TRACE);
  925. if (_readOnly) return;
  926. if (sender is this) return;
  927. foreach (itm; _areas.getItems()) { mixin(S_TRACE);
  928. if (itm.getData() is a) refData(a, itm);
  929. }
  930. }
  931. void refPackage(Object sender, Package a) { mixin(S_TRACE);
  932. if (_readOnly) return;
  933. if (sender is this) return;
  934. foreach (itm; _areas.getItems()) { mixin(S_TRACE);
  935. if (itm.getData() is a) refData(a, itm);
  936. }
  937. }
  938. static void staticCallRefArea(AreaTable v, Commons comm, AbstractArea area) { mixin(S_TRACE);
  939. auto a = cast(Area)area;
  940. if (a) { mixin(S_TRACE);
  941. comm.refArea.call(v, a);
  942. return;
  943. }
  944. auto b = cast(Battle)area;
  945. if (b) { mixin(S_TRACE);
  946. comm.refBattle.call(v, b);
  947. return;
  948. }
  949. auto p = cast(Package)area;
  950. if (p) { mixin(S_TRACE);
  951. comm.refPackage.call(v, p);
  952. return;
  953. }
  954. }
  955. void callRefArea(AbstractArea area) { mixin(S_TRACE);
  956. if (_readOnly) return;
  957. staticCallRefArea(this, _comm, area);
  958. }
  959. void refreshIDs(bool callRef) { mixin(S_TRACE);
  960. if (_readOnly) return;
  961. if (!_areas || _areas.isDisposed()) return;
  962. if (callRef) _incSearch.close();
  963. foreach (itm; _areas.getItems()) { mixin(S_TRACE);
  964. auto area = cast(AbstractArea) itm.getData();
  965. if (!area) continue;
  966. auto str = to!(string)(area.id);
  967. if (callRef && str != itm.getText(ID)) callRefArea(area);
  968. itm.setText(ID, str);
  969. }
  970. }
  971. void sort() { mixin(S_TRACE);
  972. if (_areas.getSortColumn() is null || _areas.getSortColumn() is _idSorter.column) { mixin(S_TRACE);
  973. _idSorter.doSort(_areas.getSortDirection());
  974. } else if (_areas.getSortColumn() is _nameSorter.column) { mixin(S_TRACE);
  975. _nameSorter.doSort(_areas.getSortDirection());
  976. } else if (_areas.getSortColumn() is _ucSorter.column) { mixin(S_TRACE);
  977. _ucSorter.doSort(_areas.getSortDirection());
  978. } else assert (0);
  979. }
  980. @property
  981. bool showSummary() { mixin(S_TRACE);
  982. if (!_areas || _areas.isDisposed()) return false;
  983. return 0 < _areas.getItemCount() && cast(Summary)_areas.getItem(0).getData();
  984. }
  985. @property
  986. int countAllAreas() { mixin(S_TRACE);
  987. auto c = areaCount + battleCount + packageCount;
  988. if (showSummary) { mixin(S_TRACE);
  989. return 1 + c;
  990. }
  991. return c;
  992. }
  993. class DragDir : DragSourceAdapter {
  994. override void dragStart(DragSourceEvent e) { mixin(S_TRACE);
  995. e.doit = false;
  996. auto tree = cast(Tree)(cast(DragSource) e.getSource()).getControl();
  997. if (!tree) return;
  998. if (!tree.isFocusControl()) return;
  999. auto sels = tree.getSelection();
  1000. if (!sels.length) return;
  1001. auto dir = cast(DirTree)sels[0].getData();
  1002. if (!dir) return;
  1003. if (!dir.parent) return;
  1004. e.doit = true;
  1005. }
  1006. override void dragSetData(DragSourceEvent e) { mixin(S_TRACE);
  1007. if (XMLBytesTransfer.getInstance().isSupportedType(e.dataType)) { mixin(S_TRACE);
  1008. auto tree = cast(Tree)(cast(DragSource) e.getSource()).getControl();
  1009. auto dir = cast(DirTree)tree.getSelection()[0].getData();
  1010. auto doc = XNode.create("TablePath", dir.path);
  1011. doc.newAttr("summaryId", _summ.id);
  1012. e.data = bytesFromXML(doc.text);
  1013. }
  1014. }
  1015. override void dragFinished(DragSourceEvent e) { mixin(S_TRACE);
  1016. // ????
  1017. }
  1018. }
  1019. class DropDir : DropTargetAdapter {
  1020. private void move(DropTargetEvent e) { mixin(S_TRACE);
  1021. e.detail = (!_readOnly && e.item !is null && cast(TreeItem)e.item && cast(DirTree)(cast(TreeItem)e.item).getData()) ? DND.DROP_MOVE : DND.DROP_NONE;
  1022. }
  1023. override void dragEnter(DropTargetEvent e){ mixin(S_TRACE);
  1024. move(e);
  1025. }
  1026. override void dragOver(DropTargetEvent e){ mixin(S_TRACE);
  1027. move(e);
  1028. }
  1029. override void drop(DropTargetEvent e){ mixin(S_TRACE);
  1030. if (_readOnly) return;
  1031. if (!isXMLBytes(e.data)) return;
  1032. string xml = bytesToXML(e.data);
  1033. e.detail = DND.DROP_NONE;
  1034. try { mixin(S_TRACE);
  1035. // ??????
  1036. auto node = XNode.parse(xml);
  1037. auto itm = cast(TreeItem)e.item;
  1038. auto dir = cast(DirTree)itm.getData();
  1039. auto path = dir.path;
  1040. if (node.name == "TablePath") {
  1041. if (_summ.id != AbstractArea.summaryId(node)) return;
  1042. auto oldPath = node.value;
  1043. auto removePath = node.value;
  1044. if (oldPath == "") return;
  1045. if (0 == icmp(path, oldPath)) return;
  1046. auto nDir = oldPath.split("\\")[$ - 1];
  1047. oldPath ~= "\\";
  1048. if (istartsWith(path, oldPath)) return; // ????????????????
  1049. // ?????????????
  1050. foreach (sub; dir.subDirs) {
  1051. if (0 == icmp(sub.name, nDir)) return;
  1052. }
  1053. ATUndo[] undos;
  1054. void put(AbstractArea area) {
  1055. if (area.name.istartsWith(oldPath)) {
  1056. ulong id;
  1057. TypeInfo type;
  1058. getInfoFromArea(area, id, type);
  1059. undos ~= new UndoEdit(this.outer, _comm, _summ, id, type);
  1060. auto p = path;
  1061. if (p != "") p ~= "\\";
  1062. area.name = p ~ nDir ~ "\\" ~ area.name[oldPath.length .. $];
  1063. callRefArea(area);
  1064. }
  1065. }
  1066. foreach (a; _summ.areas) put(a);
  1067. foreach (a; _summ.battles) put(a);
  1068. foreach (a; _summ.packages) put(a);
  1069. if (!undos.length) {
  1070. undos ~= new UndoIDs(this.outer, _comm, _summ);
  1071. }
  1072. auto removeItm = findDirTree(removePath);
  1073. auto removeDir = cast(DirTree)removeItm.getData();
  1074. removeDir.parent.subDirs.remove(removeDir);
  1075. new DirTree(dir, removeItm.getText());
  1076. sortDirTree();
  1077. refreshDirTree();
  1078. _undo ~= new ATUndoArr(undos);
  1079. } else if (_summ.id == AbstractArea.summaryId(node)) {
  1080. auto area = getSelectionArea();
  1081. ulong id;
  1082. TypeInfo type;
  1083. getInfoFromArea(area, id, type);
  1084. storeEdit(id, type);
  1085. area.dirName = dir.path;
  1086. callRefArea(area);
  1087. } else {
  1088. _dirTree.setSelection([itm]);
  1089. updateDirSel();
  1090. pasteImpl(node);
  1091. }
  1092. refreshAreas();
  1093. sort();
  1094. refreshStatusLine();
  1095. _comm.refreshToolBar();
  1096. } catch (Exception e) { mixin (S_TRACE);
  1097. debugln(e);
  1098. }
  1099. }
  1100. }
  1101. class DragArea : DragSourceAdapter {
  1102. AbstractArea _data;
  1103. override void dragStart(DragSourceEvent e) { mixin(S_TRACE);
  1104. auto tbl = cast(Table) (cast(DragSource) e.getSource()).getControl();
  1105. e.doit = tbl.isFocusControl() && 0 <= tbl.getSelectionIndex() && cast(AbstractArea)tbl.getSelection()[0].getData();
  1106. }
  1107. override void dragSetData(DragSourceEvent e) { mixin(S_TRACE);
  1108. if (XMLBytesTransfer.getInstance().isSupportedType(e.dataType)) { mixin(S_TRACE);
  1109. auto tbl = cast(Table) (cast(DragSource) e.getSource()).getControl();
  1110. int i = tbl.getSelectionIndex();
  1111. assert (0 <= i);
  1112. _data = cast(AbstractArea)tbl.getItem(i).getData();
  1113. assert (_data !is null);
  1114. e.data = bytesFromXML(_data.toXML(new XMLOption(_prop.sys), _summ.id));
  1115. }
  1116. }
  1117. override void dragFinished(DragSourceEvent e) { mixin(S_TRACE);
  1118. if (_readOnly) return;
  1119. if (e.detail == DND.DROP_MOVE) { mixin(S_TRACE);
  1120. auto area = _data;
  1121. _summ.remove(area);
  1122. delItem(area);
  1123. if (cast(Area) area) { mixin(S_TRACE);
  1124. _comm.delArea.call(cast(Area) area);
  1125. } else if (cast(Battle) area) { mixin(S_TRACE);
  1126. _comm.delBattle.call(cast(Battle) area);
  1127. } else { mixin(S_TRACE);
  1128. assert (cast(Package) area);
  1129. _comm.delPackage.call(cast(Package) area);
  1130. }
  1131. refreshStatusLine();
  1132. _comm.refreshToolBar();
  1133. }
  1134. }
  1135. }
  1136. class DropArea : DropTargetAdapter {
  1137. override void dragEnter(DropTargetEvent e){ mixin(S_TRACE);
  1138. e.detail = !_readOnly && _areas.getItemCount() == countAllAreas ? DND.DROP_MOVE : DND.DROP_NONE;
  1139. }
  1140. override void dragOver(DropTargetEvent e){ mixin(S_TRACE);
  1141. e.detail = !_readOnly && _areas.getItemCount() == countAllAreas ? DND.DROP_MOVE : DND.DROP_NONE;
  1142. }
  1143. override void drop(DropTargetEvent e){ mixin(S_TRACE);
  1144. if (_readOnly) return;
  1145. if (!isXMLBytes(e.data)) return;
  1146. e.detail = DND.DROP_NONE;
  1147. string xml = bytesToXML(e.data);
  1148. try { mixin(S_TRACE);
  1149. scope node = XNode.parse(xml);
  1150. TypeInfo tid;
  1151. if (node.name == Area.XML_NAME) { mixin(S_TRACE);
  1152. tid = typeid(Area);
  1153. } else if (node.name == Battle.XML_NAME) { mixin(S_TRACE);
  1154. tid = typeid(Battle);
  1155. } else if (node.name == Package.XML_NAME) { mixin(S_TRACE);
  1156. tid = typeid(Package);
  1157. } else { mixin(S_TRACE);
  1158. return;
  1159. }
  1160. bool sortedID = _areas.getSortColumn() is null || _areas.getSortColumn() is _idSorter.column;
  1161. auto tbl = cast(Table) (cast(DropTarget) e.getSource()).getControl();
  1162. auto toItm = tbl.getItem(tbl.toControl(e.x, e.y));
  1163. Object toData = toItm ? toItm.getData() : null;
  1164. int getIndex(AbstractArea area) { mixin(S_TRACE);
  1165. int index;
  1166. if (auto a = cast(Area)area) { mixin(S_TRACE);
  1167. if (toItm && cast(Summary)toData) { mixin(S_TRACE);
  1168. index = 0;
  1169. } else if (!toItm || cast(Battle)toData || cast(Package)toData) { mixin(S_TRACE);
  1170. index = _summ.areas.length;
  1171. } else { mixin(S_TRACE);
  1172. index = _summ.indexOf(cast(Area)toData);
  1173. }
  1174. } else if (auto a = cast(Battle)area) { mixin(S_TRACE);
  1175. if (toItm && (cast(Summary)toData || cast(Area)toData)) { mixin(S_TRACE);
  1176. index = 0;
  1177. } else if (!toItm || cast(Package)toData) { mixin(S_TRACE);
  1178. index = _summ.battles.length;
  1179. } else { mixin(S_TRACE);
  1180. index = _summ.indexOf(cast(Battle)toData);
  1181. }
  1182. } else if (auto a = cast(Package)area) { mixin(S_TRACE);
  1183. if (toItm && (cast(Summary)toData || cast(Area)toData || cast(Battle)toData)) { mixin(S_TRACE);
  1184. index = 0;
  1185. } else if (!toItm) { mixin(S_TRACE);
  1186. index = _summ.packages.length;
  1187. } else { mixin(S_TRACE);
  1188. index = _summ.indexOf(cast(Package)toData);
  1189. }
  1190. } else assert (0);
  1191. return index;
  1192. }
  1193. if (_summ.id == AbstractArea.summaryId(node)) { mixin(S_TRACE);
  1194. // ?????????
  1195. if (!sortedID) return;
  1196. int fromIndex = tbl.getSelectionIndex();
  1197. if (showSummary && fromIndex < 1) return;
  1198. auto area = cast(AbstractArea)tbl.getItem(fromIndex).getData();
  1199. int index = getIndex(area);
  1200. void put(A)(A a) { mixin(S_TRACE);
  1201. int moveIndex = _summ.indexOf(a);
  1202. if (moveIndex == index) return;
  1203. storeMove(moveIndex, index, typeid(typeof(a)));
  1204. _summ.insert(index, a);
  1205. }
  1206. if (auto a = cast(Area)area) { mixin(S_TRACE);
  1207. put(a);
  1208. } else if (auto a = cast(Battle)area) { mixin(S_TRACE);
  1209. put(a);
  1210. } else if (auto a = cast(Package)area) { mixin(S_TRACE);
  1211. put(a);
  1212. } else assert (0);
  1213. callRefArea(area);
  1214. refreshAreas();
  1215. sort();
  1216. select(area);
  1217. refreshStatusLine();
  1218. _comm.refreshToolBar();
  1219. e.detail = DND.DROP_NONE;
  1220. } else { mixin(S_TRACE);
  1221. // ???????????
  1222. AbstractArea area;
  1223. auto ver = new XMLInfo(_prop.sys, LATEST_VERSION);
  1224. ulong[] a, b, p;
  1225. saveIDs(_summ, a, b, p);
  1226. if (tid == typeid(Area)) { mixin(S_TRACE);
  1227. area = Area.createFromNode(node, ver);
  1228. if (_dirMode) area.dirName = _dir;
  1229. int index = getIndex(area);
  1230. _summ.insert(index, cast(Area) area);
  1231. storeInsert(area.id, tid, a, b, p);
  1232. index = _summ.indexOf(cast(Area) area);
  1233. newAreaItem(index);
  1234. } else if (tid == typeid(Battle)) { mixin(S_TRACE);
  1235. area = Battle.createFromNode(node, ver);
  1236. if (_dirMode) area.dirName = _dir;
  1237. int index = getIndex(area);
  1238. _summ.insert(index, cast(Battle) area);
  1239. storeInsert(area.id, tid, a, b, p);
  1240. index = _summ.indexOf(cast(Battle) area);
  1241. newBattleItem(index);
  1242. } else { mixin(S_TRACE);
  1243. assert (tid == typeid(Package));
  1244. area = Package.createFromNode(node, ver);
  1245. if (_dirMode) area.dirName = _dir;
  1246. int index = getIndex(area);
  1247. _summ.insert(index, cast(Package) area);
  1248. storeInsert(area.id, tid, a, b, p);
  1249. index = _summ.indexOf(cast(Package) area);
  1250. newPackageItem(index);
  1251. }
  1252. e.detail = DND.DROP_NONE;
  1253. refreshIDs(true);
  1254. sort();
  1255. select(area);
  1256. _comm.refUseCount.call();
  1257. refreshStatusLine();
  1258. _comm.refreshToolBar();
  1259. }
  1260. } catch (Exception e) { mixin (S_TRACE);
  1261. debugln(e);
  1262. }
  1263. }
  1264. }
  1265. int indexOf(in AbstractArea area) { mixin(S_TRACE);
  1266. foreach (i, itm; _areas.getItems()) { mixin(S_TRACE);
  1267. if (itm.getData() is area) { mixin(S_TRACE);
  1268. return i;
  1269. }
  1270. }
  1271. return -1;
  1272. }
  1273. void __refreshUseCount() { mixin(S_TRACE);
  1274. foreach (itm; _areas.getItems()) { mixin(S_TRACE);
  1275. auto element = itm.getData();
  1276. if (cast(Area) element) { mixin(S_TRACE);
  1277. itm.setText(2, to!(string)(_summ.useCounter.area.get(toAreaId((cast(AbstractArea) element).id))));
  1278. } else if (cast(Battle) element) { mixin(S_TRACE);
  1279. itm.setText(2, to!(string)(_summ.useCounter.battle.get(toBattleId((cast(AbstractArea) element).id))));
  1280. } else if (cast(Package) element) { mixin(S_TRACE);
  1281. itm.setText(2, to!(string)(_summ.useCounter.packages.get(toPackageId((cast(AbstractArea) element).id))));
  1282. }
  1283. }
  1284. }
  1285. class TreeMListener : MouseAdapter {
  1286. public override void mouseDoubleClick(MouseEvent e) { mixin(S_TRACE);
  1287. if (_dirTree.isFocusControl() && e.button == 1) { mixin(S_TRACE);
  1288. auto itm = _dirTree.getItem(new Point(e.x, e.y));
  1289. if (itm && cast(Summary)itm.getData()) { mixin(S_TRACE);
  1290. editSummary();
  1291. }
  1292. }
  1293. }
  1294. }
  1295. class TreeKListener : KeyAdapter {
  1296. public override void keyPressed(KeyEvent e) { mixin(S_TRACE);
  1297. if (_dirTree.isFocusControl() && e.character == SWT.CR) { mixin(S_TRACE);
  1298. auto sels = _dirTree.getSelection();
  1299. if (!sels.length) return;
  1300. auto sel = sels[0];
  1301. if (cast(Summary)sel.getData()) { mixin(S_TRACE);
  1302. editSummary();
  1303. }
  1304. }
  1305. }
  1306. }
  1307. class MListener : MouseAdapter {
  1308. public override void mouseUp(MouseEvent e) { mixin(S_TRACE);
  1309. if (e.button == 2) { mixin(S_TRACE);
  1310. auto itm = _areas.getItem(new Point(e.x, e.y));
  1311. if (itm && cast(Summary)itm.getData()) { mixin(S_TRACE);
  1312. editSummary();
  1313. } else { mixin(S_TRACE);
  1314. if (_prop.var.etc.clickIsOpenEvent) { mixin(S_TRACE);
  1315. openAreaScene(e.x, e.y, true);
  1316. } else { mixin(S_TRACE);
  1317. openAreaEvent(e.x, e.y, true);
  1318. }
  1319. }
  1320. }
  1321. }
  1322. public override void mouseDoubleClick(MouseEvent e) { mixin(S_TRACE);
  1323. if (_areas.isFocusControl() && e.button == 1) { mixin(S_TRACE);
  1324. auto itm = _areas.getItem(new Point(e.x, e.y));
  1325. if (itm && cast(Summary)itm.getData()) { mixin(S_TRACE);
  1326. editSummary();
  1327. } else { mixin(S_TRACE);
  1328. bool shift = 0 != (e.stateMask & SWT.SHIFT);
  1329. if (_prop.var.etc.clickIsOpenEvent) shift = !shift;
  1330. if (shift) { mixin(S_TRACE);
  1331. openAreaEvent(true);
  1332. } else { mixin(S_TRACE);
  1333. openAreaScene(true);
  1334. }
  1335. }
  1336. }
  1337. }
  1338. }
  1339. class KListener : KeyAdapter {
  1340. public override void keyPressed(KeyEvent e) { mixin(S_TRACE);
  1341. if (_areas.isFocusControl() && e.character == SWT.CR) { mixin(S_TRACE);
  1342. auto sel = _areas.getSelectionIndex();
  1343. if (sel == -1) return;
  1344. if (cast(Summary)_areas.getItem(sel).getData()) { mixin(S_TRACE);
  1345. editSummary();
  1346. } else { mixin(S_TRACE);
  1347. bool shift = 0 != (e.stateMask & SWT.SHIFT);
  1348. if (_prop.var.etc.clickIsOpenEvent) shift = !shift;
  1349. if (shift) { mixin(S_TRACE);
  1350. openAreaEvent(true);
  1351. } else { mixin(S_TRACE);
  1352. openAreaScene(true);
  1353. }
  1354. }
  1355. }
  1356. }
  1357. }
  1358. class ADListener : DisposeListener {
  1359. override void widgetDisposed(DisposeEvent e) { mixin(S_TRACE);
  1360. _dirs = null;
  1361. _dir = "";
  1362. _areas = null;
  1363. _dirTree = null;
  1364. if (!_readOnly) {
  1365. _comm.refArea.remove(&refArea);
  1366. _comm.refBattle.remove(&refBattle);
  1367. _comm.refPackage.remove(&refPackage);
  1368. _comm.refUseCount.remove(&__refreshUseCount);
  1369. _comm.replText.remove(&replText);
  1370. _comm.replText.remove(&refresh);
  1371. _comm.refScenario.remove(&refScenario);
  1372. _comm.refScenarioName.remove(&refScenarioName);
  1373. _comm.refUndoMax.remove(&refUndoMax);
  1374. }
  1375. _comm.refAreaTable.remove(&refreshAreas);
  1376. }
  1377. }
  1378. static class DirTree {
  1379. DirTree parent;
  1380. string name;
  1381. DirTree[] subDirs;
  1382. this (DirTree parent, string name) { mixin (S_TRACE);
  1383. this.parent = parent;
  1384. this.name = name;
  1385. if (parent) { mixin (S_TRACE);
  1386. parent.subDirs ~= this;
  1387. }
  1388. }
  1389. @property
  1390. const
  1391. string path() { mixin (S_TRACE);
  1392. if (!parent) return name;
  1393. auto path = parent.path;
  1394. return path == "" ? name : path ~ "\\" ~ name;
  1395. }
  1396. @property
  1397. const
  1398. DirTree dup() { mixin (S_TRACE);
  1399. DirTree recurse(DirTree parent, in DirTree dir) { mixin (S_TRACE);
  1400. auto dir2 = new DirTree(parent, dir.name);
  1401. foreach (sub; dir.subDirs) { mixin (S_TRACE);
  1402. recurse(dir2, sub);
  1403. }
  1404. return dir2;
  1405. }
  1406. return recurse(null, this);
  1407. }
  1408. }
  1409. private void delDirTree(string path) {
  1410. if (_readOnly) return;
  1411. if (path == "") return;
  1412. auto itm = findDirTree(path);
  1413. auto dir = cast(DirTree)itm.getData();
  1414. assert (dir !is null);
  1415. assert (dir.parent !is null);
  1416. dir.parent.subDirs.remove(dir);
  1417. itm.dispose();
  1418. }
  1419. private void replText() {
  1420. if (_readOnly) return;
  1421. constructDirTree(false);
  1422. }
  1423. private void constructDirTree(bool add) { mixin(S_TRACE);
  1424. string[] stored;
  1425. if (add && _dirs) { mixin(S_TRACE);
  1426. void store(DirTree dir) { mixin(S_TRACE);
  1427. stored ~= dir.path;
  1428. foreach (sub; dir.subDirs) store(sub);
  1429. }
  1430. store(_dirs);
  1431. }
  1432. _dirs = new DirTree(null, "");
  1433. DirTree[string] itmTable;
  1434. itmTable[""] = _dirs;
  1435. void put(string dirName) { mixin (S_TRACE);
  1436. auto dirs = .split(dirName, "\\");
  1437. auto itm = _dirs;
  1438. foreach (i, dir; dirs) { mixin (S_TRACE);
  1439. auto fPath = dirs[0 .. i + 1].join("\\");
  1440. auto path = fPath.toLower();
  1441. auto p = path in itmTable;
  1442. if (p) { mixin (S_TRACE);
  1443. itm = *p;
  1444. } else { mixin (S_TRACE);
  1445. auto sub = new DirTree(itm, dir);
  1446. itm = sub;
  1447. itmTable[path] = sub;
  1448. }
  1449. }
  1450. }
  1451. foreach (a; _summ.areas) put(a.dirName);
  1452. foreach (a; _summ.battles) put(a.dirName);
  1453. foreach (a; _summ.packages) put(a.dirName);
  1454. foreach (s; stored) put(s);
  1455. sortDirTree();
  1456. }
  1457. private string putDir(DirTree parent, string dirName) { mixin (S_TRACE);
  1458. auto dirs = .split(dirName, "\\");
  1459. foreach (i, dir; dirs) { mixin (S_TRACE);
  1460. bool exists = false;
  1461. foreach (sub; parent.subDirs) { mixin (S_TRACE);
  1462. if (0 == icmp(sub.name, dir)) { mixin (S_TRACE);
  1463. parent = sub;
  1464. exists = true;
  1465. break;
  1466. }
  1467. }
  1468. if (!exists) {
  1469. parent = new DirTree(parent, dir);
  1470. }
  1471. }
  1472. return parent.path;
  1473. }
  1474. private void sortDirTree() {
  1475. void recurse(DirTree dir) { mixin(S_TRACE);
  1476. if (_prop.var.etc.logicalSort) { mixin(S_TRACE);
  1477. .sortDlg(dir.subDirs, (DirTree a, DirTree b) => incmp(a.name, b.name) < 0);
  1478. } else { mixin(S_TRACE);
  1479. .sortDlg(dir.subDirs, (DirTree a, DirTree b) => icmp(a.name, b.name) < 0);
  1480. }
  1481. foreach (sub; dir.subDirs) recurse(sub);
  1482. }
  1483. recurse(_dirs);
  1484. }
  1485. private TreeItem findDirTree(string path) { mixin(S_TRACE);
  1486. auto dirs = .split(path, "\\");
  1487. auto itm = rootDir;
  1488. foreach (i, dir; dirs) { mixin(S_TRACE);
  1489. foreach (sub; itm.getItems()) { mixin(S_TRACE);
  1490. auto ds = cast(DirTree)sub.getData();
  1491. if (0 == icmp(ds.name, dir)) { mixin(S_TRACE);
  1492. itm = sub;
  1493. break;
  1494. }
  1495. }
  1496. }
  1497. return itm;
  1498. }
  1499. private void refreshDirTree() { mixin(S_TRACE);
  1500. if (!_dirTree) return;
  1501. if (_areaDirEdit) _areaDirEdit.cancel();
  1502. bool selSummary = false;
  1503. auto sel = "";
  1504. auto sels = _dirTree.getSelection();
  1505. if (sels.length) { mixin (S_TRACE);
  1506. auto path = cast(DirTree)sels[0].getData();
  1507. if (path) { mixin (S_TRACE);
  1508. sel = path.path;
  1509. } else { mixin (S_TRACE);
  1510. assert (cast(Summary)sels[0].getData() !is null);
  1511. selSummary = true;
  1512. }
  1513. }
  1514. _dirTree.removeAll();
  1515. if (!_summ) return;
  1516. if (_prop.var.etc.showSummaryInAreaTable) { mixin (S_TRACE);
  1517. auto itm = new TreeItem(_dirTree, SWT.NONE);
  1518. itm.setImage(_prop.images.summary);
  1519. itm.setText(_summ.scenarioName);
  1520. itm.setData(_summ);
  1521. if (selSummary) { mixin (S_TRACE);
  1522. _dirTree.setSelection([itm]);
  1523. }
  1524. }
  1525. void recurse(T)(T tree, DirTree dir) { mixin (S_TRACE);
  1526. auto itm = new TreeItem(tree, SWT.NONE);
  1527. static if (is(T:Tree)) {
  1528. itm.setText(_prop.msgs.areaDirRoot);
  1529. } else {
  1530. itm.setText(dir.name);
  1531. }
  1532. itm.setImage(_prop.images.areaDir);
  1533. itm.setData(dir);
  1534. if (!selSummary && 0 == icmp(sel, dir.path)) { mixin (S_TRACE);
  1535. _dirTree.setSelection([itm]);
  1536. } else if (!_dirTree.getSelection().length) { mixin (S_TRACE);
  1537. _dirTree.setSelection([itm]);
  1538. }
  1539. foreach (sub; dir.subDirs) { mixin (S_TRACE);
  1540. recurse(itm, sub);
  1541. }
  1542. }
  1543. recurse(_dirTree, _dirs);
  1544. _dirTree.treeExpandedAll();
  1545. _dirTree.showSelection();
  1546. }
  1547. private Image areaImage(in Area a) {
  1548. return _summ.startArea == a.id ? _prop.images.startArea : _prop.images.area;
  1549. }
  1550. private void updateDirSel() { mixin(S_TRACE);
  1551. auto sels = _dirTree.getSelection();
  1552. if (!sels.length) return;
  1553. auto sel = cast(DirTree)sels[0].getData();
  1554. if (!sel) return;
  1555. _dir = sel.path;
  1556. refreshAreasImpl(true);
  1557. }
  1558. private void refreshAreas() { mixin(S_TRACE);
  1559. refreshAreasImpl(false);
  1560. }
  1561. private void refreshAreasImpl(bool selDir) { mixin(S_TRACE);
  1562. if (!_areas || _areas.isDisposed()) return;
  1563. _parent.setRedraw(false);
  1564. scope (exit) _parent.setRedraw(true);
  1565. if (!selDir) refreshDirTree();
  1566. int topIndex = _areas.getTopIndex();
  1567. auto sel = _areas.getSelectionIndex();
  1568. if (_summ) { mixin(S_TRACE);
  1569. size_t i = 0;
  1570. if (!_dirMode && _prop.var.etc.showSummaryInAreaTable) { mixin(S_TRACE);
  1571. refSummary();
  1572. i++;
  1573. }
  1574. void put(AbstractArea a) { mixin(S_TRACE);
  1575. if (_dirMode) { mixin(S_TRACE);
  1576. if (0 != icmp(a.dirName, _dir)) return;
  1577. if (!_incSearch.match(a.baseName, a)) return;
  1578. } else { mixin(S_TRACE);
  1579. if (!_incSearch.match(a.name, a)) return;
  1580. }
  1581. refData2(a, i < _areas.getItemCount() ? _areas.getItem(i) : new TableItem(_areas, SWT.NONE));
  1582. i++;
  1583. }
  1584. foreach (a; _summ.areas) { mixin(S_TRACE);
  1585. put(a);
  1586. }
  1587. foreach (a; _summ.battles) { mixin(S_TRACE);
  1588. put(a);
  1589. }
  1590. foreach (a; _summ.packages) { mixin(S_TRACE);
  1591. put(a);
  1592. }
  1593. while (i < _areas.getItemCount()) { mixin(S_TRACE);
  1594. _areas.getItem(i).dispose();
  1595. }
  1596. sort();
  1597. } else { mixin(S_TRACE);
  1598. _areas.removeAll();
  1599. }
  1600. _areas.setTopIndex(topIndex);
  1601. if (sel < 0 || _areas.getItemCount() <= sel) { mixin(S_TRACE);
  1602. _areas.select(.min(_areas.getItemCount() - 1, sel));
  1603. }
  1604. _areas.showSelection();
  1605. refreshStatusLine();
  1606. _comm.refreshToolBar();
  1607. }
  1608. void refSummary() { mixin(S_TRACE);
  1609. if (!_summ) return;
  1610. TableItem itm;
  1611. if (_areas.getItemCount()) { mixin(S_TRACE);
  1612. if (!showSummary) return;
  1613. itm = _areas.getItem(0);
  1614. } else { mixin(S_TRACE);
  1615. itm = new TableItem(_areas, SWT.NONE, 0);
  1616. }
  1617. itm.setImage(0, _prop.images.summary);
  1618. itm.setText(ID, "-");
  1619. itm.setText(NA

Large files files are truncated, but you can click here to view the full file