PageRenderTime 86ms CodeModel.GetById 35ms 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
  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(NAME, _summ.scenarioName);
  1620. itm.setText(UC, "-");
  1621. itm.setData(_summ);
  1622. }
  1623. void updateAreaImage() { mixin(S_TRACE);
  1624. foreach (itm; _areas.getItems()) { mixin(S_TRACE);
  1625. if (auto a = cast(Area)itm.getData()) { mixin(S_TRACE);
  1626. itm.setImage(0, areaImage(a));
  1627. }
  1628. }
  1629. }
  1630. void item(AbstractArea a, Image img, int uc, int index = -1) { mixin(S_TRACE);
  1631. TableItem itm;
  1632. if (index >= 0) { mixin(S_TRACE);
  1633. itm = new TableItem(_areas, SWT.NONE, index);
  1634. } else { mixin(S_TRACE);
  1635. itm = new TableItem(_areas, SWT.NONE);
  1636. }
  1637. itm.setImage(0, img);
  1638. itm.setText(ID, to!(string)(a.id));
  1639. itm.setText(NAME, _dirMode ? a.baseName : a.name);
  1640. itm.setText(UC, to!(string)(uc));
  1641. itm.setData(a);
  1642. }
  1643. void refData2(AbstractArea a, TableItem itm) { mixin(S_TRACE);
  1644. if (auto area = cast(Area)a) { mixin(S_TRACE);
  1645. itm.setImage(0, areaImage(area));
  1646. refData(area, itm);
  1647. } else if (auto btl = cast(Battle)a) { mixin(S_TRACE);
  1648. itm.setImage(0, _prop.images.battle);
  1649. refData(btl, itm);
  1650. } else if (auto pkg = cast(Package)a) { mixin(S_TRACE);
  1651. itm.setImage(0, _prop.images.packages);
  1652. refData(pkg, itm);
  1653. } else assert (0);
  1654. }
  1655. void refData(A)(A a, TableItem itm) { mixin(S_TRACE);
  1656. itm.setText(ID, to!(string)(a.id));
  1657. itm.setText(NAME, _dirMode ? a.baseName : a.name);
  1658. itm.setText(UC, to!(string)(_summ.useCounter.get(A.toID(a.id))));
  1659. itm.setData(a);
  1660. }
  1661. private int newAreaItem(int index) { mixin(S_TRACE);
  1662. _incSearch.close();
  1663. auto a = _summ.areas[index];
  1664. if (showSummary) index++;
  1665. item(a, areaImage(a), _summ.useCounter.get(toAreaId(a.id)), index);
  1666. return index;
  1667. }
  1668. private int newBattleItem(int index) { mixin(S_TRACE);
  1669. _incSearch.close();
  1670. auto a = _summ.battles[index];
  1671. index += _summ.areas.length;
  1672. if (showSummary) index++;
  1673. item(a, _prop.images.battle, _summ.useCounter.get(toBattleId(a.id)), index);
  1674. return index;
  1675. }
  1676. private int newPackageItem(int index) { mixin(S_TRACE);
  1677. _incSearch.close();
  1678. auto a = _summ.packages[index];
  1679. index += _summ.areas.length + _summ.battles.length;
  1680. if (showSummary) index++;
  1681. item(a, _prop.images.packages, _summ.useCounter.get(toPackageId(a.id)), index);
  1682. return index;
  1683. }
  1684. private void addAreaItem(int index) { mixin(S_TRACE);
  1685. auto a = _summ.areas[index];
  1686. if (!_incSearch.match(a.name, a)) return;
  1687. index = showSummary ? 1 : 0;
  1688. for (; index < _areas.getItemCount(); index++) { mixin(S_TRACE);
  1689. if (!cast(Area)_areas.getItem(index).getData()) break;
  1690. }
  1691. item(a, areaImage(a), _summ.useCounter.get(toAreaId(a.id)), index);
  1692. }
  1693. private void addBattleItem(int index) { mixin(S_TRACE);
  1694. auto a = _summ.battles[index];
  1695. if (!_incSearch.match(a.name, a)) return;
  1696. index = showSummary ? 1 : 0;
  1697. for (; index < _areas.getItemCount(); index++) { mixin(S_TRACE);
  1698. auto data = _areas.getItem(index).getData();
  1699. if (!cast(Area)data && !cast(Battle)data) break;
  1700. }
  1701. item(a, _prop.images.battle, _summ.useCounter.get(toBattleId(a.id)), index);
  1702. }
  1703. private void addPackageItem(int index) { mixin(S_TRACE);
  1704. auto a = _summ.packages[index];
  1705. if (!_incSearch.match(a.name, a)) return;
  1706. index = _areas.getItemCount();
  1707. item(a, _prop.images.packages, _summ.useCounter.get(toPackageId(a.id)), index);
  1708. }
  1709. private class SListener : SelectionAdapter {
  1710. override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  1711. refreshStatusLine();
  1712. _comm.refreshToolBar();
  1713. }
  1714. }
  1715. bool _sortProc = false;
  1716. void refSortParams(Object sender, int column, int dir) { mixin(S_TRACE);
  1717. if (sender is this) return;
  1718. if (_sortProc) return;
  1719. _sortProc = true;
  1720. scope (exit) _sortProc = false;
  1721. final switch (column) {
  1722. case ID:
  1723. _idSorter.doSort(dir);
  1724. break;
  1725. case NAME:
  1726. _nameSorter.doSort(dir);
  1727. break;
  1728. case UC:
  1729. _ucSorter.doSort(dir);
  1730. break;
  1731. }
  1732. }
  1733. void sorted() { mixin(S_TRACE);
  1734. if (_sortProc) return;
  1735. _sortProc = true;
  1736. scope (exit) _sortProc = false;
  1737. if (_areas.getSortColumn() is null) return;
  1738. _comm.refImportAreasSort.call(_areas.indexOf(_areas.getSortColumn()), _areas.getSortDirection());
  1739. }
  1740. void refScenario(Summary summ) { mixin(S_TRACE);
  1741. _undo.reset();
  1742. }
  1743. void refScenarioName() { mixin(S_TRACE);
  1744. if (!_summ) return;
  1745. if (_dirMode) { mixin(S_TRACE);
  1746. if (!showTreeSummary) return;
  1747. auto itm = _dirTree.getItem(0);
  1748. itm.setText(NAME, _summ.scenarioName);
  1749. } else {
  1750. if (!showSummary) return;
  1751. auto itm = _areas.getItem(0);
  1752. itm.setText(NAME, _summ.scenarioName);
  1753. }
  1754. }
  1755. void refUndoMax() { mixin(S_TRACE);
  1756. _undo.max = _prop.var.etc.undoMaxMainView;
  1757. }
  1758. public:
  1759. this (Commons comm, Props prop, bool readOnly, Summary importTarget) { mixin(S_TRACE);
  1760. _readOnly = readOnly ? SWT.READ_ONLY : SWT.NONE;
  1761. _comm = comm;
  1762. _prop = prop;
  1763. _importTarget = importTarget;
  1764. _undo = new UndoManager(_prop.var.etc.undoMaxMainView);
  1765. }
  1766. void construct(Composite parent, FlagTable flags) { mixin(S_TRACE);
  1767. _flags = flags;
  1768. if (!_readOnly) { mixin(S_TRACE);
  1769. _comm.refArea.add(&refArea);
  1770. _comm.refBattle.add(&refBattle);
  1771. _comm.refPackage.add(&refPackage);
  1772. _comm.refUseCount.add(&__refreshUseCount);
  1773. _comm.replText.add(&replText);
  1774. _comm.replText.add(&refresh);
  1775. _comm.refScenario.add(&refScenario);
  1776. _comm.refScenarioName.add(&refScenarioName);
  1777. _comm.refUndoMax.add(&refUndoMax);
  1778. }
  1779. _comm.refAreaTable.add(&refreshAreas);
  1780. auto tableParent = parent;
  1781. _parent = parent;
  1782. _dirMode = false;
  1783. if (_prop.var.etc.showAreaDirTree) { mixin (S_TRACE);
  1784. _dirMode = true;
  1785. auto sash = new SplitPane(parent, (_readOnly ? _prop.var.etc.importAreaSashV : _prop.var.etc.areaSashV) ? SWT.VERTICAL : SWT.HORIZONTAL);
  1786. auto cl1 = new CenterLayout(SWT.HORIZONTAL | SWT.VERTICAL, 0);
  1787. cl1.fillHorizontal = true;
  1788. cl1.fillVertical = true;
  1789. auto cl2 = new CenterLayout(SWT.HORIZONTAL | SWT.VERTICAL, 0);
  1790. cl2.fillHorizontal = true;
  1791. cl2.fillVertical = true;
  1792. auto panel1 = new Composite(sash, SWT.NONE);
  1793. panel1.setLayout(cl1);
  1794. auto panel2 = new Composite(sash, SWT.NONE);
  1795. panel2.setLayout(cl2);
  1796. tableParent = panel2;
  1797. _dirTree = new Tree(panel1, SWT.SINGLE | SWT.BORDER | SWT.VIRTUAL);
  1798. initTree(_comm, _dirTree, false);
  1799. .listener(_dirTree, SWT.Selection, &updateDirSel);
  1800. if (!_readOnly) { mixin(S_TRACE);
  1801. _areaDirEdit = new TreeEdit(_comm, _dirTree, &dirEditEnd, (itm) { mixin (S_TRACE);
  1802. auto dir = cast(DirTree)itm.getData();
  1803. if (dir) { mixin (S_TRACE);
  1804. if (!dir.parent) return null;
  1805. } else assert (cast(Summary)itm.getData() !is null);
  1806. return createTextEditor(_comm, _prop, _dirTree, itm.getText());
  1807. });
  1808. }
  1809. _dirTree.addMouseListener(new TreeMListener);
  1810. _dirTree.addKeyListener(new TreeKListener);
  1811. auto menu = new Menu(_dirTree.getShell(), SWT.POP_UP);
  1812. if (_readOnly) { mixin (S_TRACE);
  1813. createMenuItem(_comm, menu, MenuID.Import, &doImport, &canDoImport);
  1814. new MenuItem(menu, SWT.SEPARATOR);
  1815. appendMenuTCPD(_comm, menu, this, false, true, false, false, false);
  1816. } else { mixin (S_TRACE);
  1817. createMenuItem(_comm, menu, MenuID.NewAreaDir, &createDir, () => !_readOnly && _dirMode && _summ !is null);
  1818. new MenuItem(menu, SWT.SEPARATOR);
  1819. createMenuItem(_comm, menu, MenuID.Undo, &this.undo, () => !_readOnly && _undo.canUndo);
  1820. createMenuItem(_comm, menu, MenuID.Redo, &this.redo, () => !_readOnly && _undo.canRedo);
  1821. new MenuItem(menu, SWT.SEPARATOR);
  1822. appendMenuTCPD(_comm, menu, this, true, true, true, true, true);
  1823. }
  1824. _dirTree.setMenu(menu);
  1825. auto drag = new DragSource(_dirTree, DND.DROP_MOVE | DND.DROP_COPY);
  1826. drag.setTransfer([XMLBytesTransfer.getInstance()]);
  1827. drag.addDragListener(new DragDir);
  1828. if (!_readOnly) { mixin (S_TRACE);
  1829. auto drop = new DropTarget(_dirTree, DND.DROP_DEFAULT | DND.DROP_MOVE);
  1830. drop.setTransfer([XMLBytesTransfer.getInstance()]);
  1831. drop.addDropListener(new DropDir);
  1832. }
  1833. }
  1834. _areas = new Table(tableParent, (_readOnly ? SWT.MULTI : SWT.SINGLE) | SWT.BORDER | SWT.FULL_SELECTION);
  1835. _areas.addDisposeListener(new ADListener);
  1836. _areas.addSelectionListener(new SListener);
  1837. _areas.setHeaderVisible(true);
  1838. auto idCol = new TableColumn(_areas, SWT.NULL);
  1839. idCol.setText(_prop.msgs.areaId);
  1840. auto nameCol = new TableColumn(_areas, SWT.NULL);
  1841. nameCol.setText(_prop.msgs.areaName);
  1842. auto countCol = new TableColumn(_areas, SWT.NULL);
  1843. countCol.setText(_prop.msgs.areaCount);
  1844. if (_readOnly) { mixin (S_TRACE);
  1845. saveColumnWidth!("prop.var.etc.importAreaIdColumn")(_prop, idCol);
  1846. saveColumnWidth!("prop.var.etc.importAreaNameColumn")(_prop, nameCol);
  1847. saveColumnWidth!("prop.var.etc.importAreaCountColumn")(_prop, countCol);
  1848. } else { mixin (S_TRACE);
  1849. saveColumnWidth!("prop.var.etc.areaIdColumn")(_prop, idCol);
  1850. saveColumnWidth!("prop.var.etc.areaNameColumn")(_prop, nameCol);
  1851. saveColumnWidth!("prop.var.etc.areaCountColumn")(_prop, countCol);
  1852. }
  1853. _areasEdit = new TableTextEdit(_comm, _prop, _areas, 1, &editEnd);
  1854. updateIncSearchParent();
  1855. auto menu = new Menu(parent.getShell(), SWT.POP_UP);
  1856. createMenuItem(_comm, menu, MenuID.IncSearch, &incSearch, null);
  1857. new MenuItem(menu, SWT.SEPARATOR);
  1858. if (_readOnly) {
  1859. createMenuItem(_comm, menu, MenuID.Import, &doImport, &canDoImport);
  1860. new MenuItem(menu, SWT.SEPARATOR);
  1861. }
  1862. if (!_comm.singleWindowMode(_prop) || _prop.var.etc.bindSceneWithEvent) { mixin(S_TRACE);
  1863. createMenuItem(_comm, menu, MenuID.EditProp, &edit, &canEdit);
  1864. } else { mixin(S_TRACE);
  1865. createMenuItem(_comm, menu, MenuID.EditScene, {openAreaScene(true);}, &canOpenAreaScene);
  1866. createMenuItem(_comm, menu, MenuID.EditEvent, {openAreaEvent(true);}, &canOpenAreaEvent);
  1867. }
  1868. new MenuItem(menu, SWT.SEPARATOR);
  1869. createMenuItem(_comm, menu, MenuID.EditSummary, &editSummary, () => _summ !is null);
  1870. new MenuItem(menu, SWT.SEPARATOR);
  1871. if (!_readOnly) { mixin(S_TRACE);
  1872. createMenuItem(_comm, menu, MenuID.NewArea, &createArea, () => !_readOnly && _summ !is null);
  1873. createMenuItem(_comm, menu, MenuID.NewBattle, &createBattle, () => !_readOnly && _summ !is null);
  1874. createMenuItem(_comm, menu, MenuID.NewPackage, &createPackage, () => !_readOnly && _summ !is null);
  1875. new MenuItem(menu, SWT.SEPARATOR);
  1876. createMenuItem(_comm, menu, MenuID.SetStartArea, &setStartArea, &canSetStartArea);
  1877. new MenuItem(menu, SWT.SEPARATOR);
  1878. createMenuItem(_comm, menu, MenuID.Undo, &undo, () => !_readOnly && _undo.canUndo);
  1879. createMenuItem(_comm, menu, MenuID.Redo, &redo, () => !_readOnly && _undo.canRedo);
  1880. new MenuItem(menu, SWT.SEPARATOR);
  1881. appendMenuTCPD(_comm, menu, this, true, true, true, true, true);
  1882. new MenuItem(menu, SWT.SEPARATOR);
  1883. createMenuItem(_comm, menu, MenuID.FindID, &replaceID, &canReplaceID);
  1884. new MenuItem(menu, SWT.SEPARATOR);
  1885. createMenuItem(_comm, menu, MenuID.ReNumbering, &reNumbering, &canReNumbering);
  1886. } else { mixin(S_TRACE);
  1887. appendMenuTCPD(_comm, menu, this, false, true, false, false, false);
  1888. }
  1889. _areas.setMenu(menu);
  1890. _areas.addMouseListener(new MListener);
  1891. _areas.addKeyListener(new KListener);
  1892. auto drag = new DragSource(_areas, DND.DROP_MOVE | DND.DROP_COPY);
  1893. drag.setTransfer([XMLBytesTransfer.getInstance()]);
  1894. drag.addDragListener(new DragArea);
  1895. if (!_readOnly) { mixin (S_TRACE);
  1896. auto drop = new DropTarget(_areas, DND.DROP_DEFAULT | DND.DROP_MOVE);
  1897. drop.setTransfer([XMLBytesTransfer.getInstance()]);
  1898. drop.addDropListener(new DropArea);
  1899. }
  1900. // ?????
  1901. _idSorter = new TableSorter!(Object)(idCol, &compID, &revCompID);
  1902. if (_readOnly) _idSorter.sortedEvent ~= &sorted;
  1903. _nameSorter = new TableSorter!(Object)(nameCol, &compName, &revCompName);
  1904. if (_readOnly) _nameSorter.sortedEvent ~= &sorted;
  1905. _ucSorter = new TableSorter!(Object)(countCol, &compUC, &revCompUC);
  1906. if (_readOnly) _ucSorter.sortedEvent ~= &sorted;
  1907. auto st = _idSorter;
  1908. int sortColumn = _readOnly ? _prop.var.etc.importAreasSortColumn : _prop.var.etc.areasSortColumn;
  1909. switch (sortColumn) {
  1910. case ID:
  1911. st = _idSorter;
  1912. break;
  1913. case NAME:
  1914. st = _nameSorter;
  1915. break;
  1916. case UC:
  1917. st = _ucSorter;
  1918. break;
  1919. default:
  1920. }
  1921. int sortDir = _readOnly ? _prop.var.etc.importAreasSortDirection : _prop.var.etc.areasSortDirection;
  1922. switch (sortDir) {
  1923. case SortDir.Up:
  1924. st.doSort(SWT.UP);
  1925. break;
  1926. case SortDir.Down:
  1927. st.doSort(SWT.DOWN);
  1928. break;
  1929. default:
  1930. // ???????
  1931. st.doSort(SWT.UP);
  1932. break;
  1933. }
  1934. if (_readOnly) { mixin(S_TRACE);
  1935. _comm.refImportAreasSort.add(&refSortParams);
  1936. }
  1937. .listener(_areas, SWT.Dispose, (Event e) { mixin(S_TRACE);
  1938. auto areas = cast(Table)e.widget;
  1939. if (_readOnly) { mixin(S_TRACE);
  1940. switch (areas.getSortDirection()) {
  1941. case SWT.UP:
  1942. _prop.var.etc.importAreasSortDirection = SortDir.Up;
  1943. break;
  1944. case SWT.DOWN:
  1945. _prop.var.etc.importAreasSortDirection = SortDir.Down;
  1946. break;
  1947. default:
  1948. // ???????
  1949. _prop.var.etc.importAreasSortDirection = SortDir.Up;
  1950. break;
  1951. }
  1952. if (areas.getSortColumn() is _idSorter.column) { mixin(S_TRACE);
  1953. _prop.var.etc.importAreasSortColumn = ID;
  1954. } else if (areas.getSortColumn() is _nameSorter.column) { mixin(S_TRACE);
  1955. _prop.var.etc.importAreasSortColumn = NAME;
  1956. } else if (areas.getSortColumn() is _ucSorter.column) { mixin(S_TRACE);
  1957. _prop.var.etc.importAreasSortColumn = UC;
  1958. } else { mixin(S_TRACE);
  1959. _prop.var.etc.importAreasSortColumn = -1;
  1960. }
  1961. _comm.refImportAreasSort.add(&refSortParams);
  1962. } else { mixin(S_TRACE);
  1963. switch (areas.getSortDirection()) {
  1964. case SWT.UP:
  1965. _prop.var.etc.areasSortDirection = SortDir.Up;
  1966. break;
  1967. case SWT.DOWN:
  1968. _prop.var.etc.areasSortDirection = SortDir.Down;
  1969. break;
  1970. default:
  1971. // ???????
  1972. _prop.var.etc.areasSortDirection = SortDir.Up;
  1973. break;
  1974. }
  1975. if (areas.getSortColumn() is _idSorter.column) { mixin(S_TRACE);
  1976. _prop.var.etc.areasSortColumn = ID;
  1977. } else if (areas.getSortColumn() is _nameSorter.column) { mixin(S_TRACE);
  1978. _prop.var.etc.areasSortColumn = NAME;
  1979. } else if (areas.getSortColumn() is _ucSorter.column) { mixin(S_TRACE);
  1980. _prop.var.etc.areasSortColumn = UC;
  1981. } else { mixin(S_TRACE);
  1982. _prop.var.etc.areasSortColumn = -1;
  1983. }
  1984. }
  1985. });
  1986. _idSorter.sortedEvent ~= &_comm.refreshToolBar;
  1987. _nameSorter.sortedEvent ~= &_comm.refreshToolBar;
  1988. _ucSorter.sortedEvent ~= &_comm.refreshToolBar;
  1989. if (_dirTree) { mixin (S_TRACE);
  1990. auto sash = cast(SplitPane)_dirTree.getParent().getParent();
  1991. if (_readOnly) { mixin (S_TRACE);
  1992. sash.setWeights([_prop.var.etc.importAreaSashL, _prop.var.etc.importAreaSashR]);
  1993. } else { mixin (S_TRACE);
  1994. sash.setWeights([_prop.var.etc.areaSashL, _prop.var.etc.areaSashR]);
  1995. }
  1996. .listener(sash, SWT.Dispose, {
  1997. auto ws = sash.getWeights();
  1998. if (_readOnly) { mixin (S_TRACE);
  1999. _prop.var.etc.importAreaSashL = ws[0];
  2000. _prop.var.etc.importAreaSashR = ws[1];
  2001. } else { mixin (S_TRACE);
  2002. _prop.var.etc.areaSashL = ws[0];
  2003. _prop.var.etc.areaSashR = ws[1];
  2004. }
  2005. });
  2006. }
  2007. }
  2008. private void updateIncSearchParent() { mixin(S_TRACE);
  2009. auto matchers = [
  2010. AdditionMatcher(MenuProps.buildMenu(.objName!Area(_prop), "A", "", false), (o) => cast(Area)o !is null),
  2011. AdditionMatcher(MenuProps.buildMenu(.objName!Battle(_prop), "B", "", false), (o) => cast(Battle)o !is null),
  2012. AdditionMatcher(MenuProps.buildMenu(.objName!Package(_prop), "P", "", false), (o) => cast(Package)o !is null)
  2013. ];
  2014. if (_dirMode) { mixin(S_TRACE);
  2015. _incSearch = new IncSearch(_comm, _dirTree.getParent().getParent(), matchers);
  2016. } else { mixin(S_TRACE);
  2017. _incSearch = new IncSearch(_comm, _areas, matchers);
  2018. }
  2019. _incSearch.modEvent ~= &refreshAreas;
  2020. }
  2021. private int toAreaIndex(int index) { mixin(S_TRACE);
  2022. index--;
  2023. return (index >= 0 && index < _summ.areas.length) ? index : -1;
  2024. }
  2025. private int toBattleIndex(int index) { mixin(S_TRACE);
  2026. index--;
  2027. return (index >= 0 && index < _summ.areas.length + _summ.battles.length)
  2028. ? index - _summ.areas.length : -1;
  2029. }
  2030. private int toPackageIndex(int index) { mixin(S_TRACE);
  2031. index--;
  2032. return (index >= 0 && index < _summ.areas.length
  2033. + _summ.battles.length + _summ.packages.length)
  2034. ? index - _summ.areas.length - _summ.battles.length : -1;
  2035. }
  2036. @property
  2037. bool canChangeVH() { mixin(S_TRACE);
  2038. return _dirTree && !_dirTree.isDisposed();
  2039. }
  2040. void changeVHSide() { mixin(S_TRACE);
  2041. if (!canChangeVH) return;
  2042. auto sash = cast(SplitPane)_dirTree.getParent().getParent();
  2043. sash = .changeVHSide(sash);
  2044. if (_readOnly) { mixin(S_TRACE);
  2045. _prop.var.etc.importAreaSashV = (sash.getStyle() & SWT.VERTICAL) != 0;
  2046. } else { mixin(S_TRACE);
  2047. _prop.var.etc.areaSashV = (sash.getStyle() & SWT.VERTICAL) != 0;
  2048. }
  2049. updateIncSearchParent();
  2050. }
  2051. @property
  2052. bool canCreateDir() { mixin(S_TRACE);
  2053. return !_readOnly && _summ && _dirTree && !_dirTree.isDisposed();
  2054. }
  2055. void createDir() { mixin(S_TRACE);
  2056. if (_readOnly) return;
  2057. if (!canCreateDir) return;
  2058. _incSearch.close();
  2059. storeEmpty();
  2060. auto itm = findDirTree(_dir);
  2061. auto dir = cast(DirTree)itm.getData();
  2062. auto sub = new DirTree(dir, createNewName(_prop.msgs.areaDirNew, (s) { mixin(S_TRACE);
  2063. foreach (dir; dir.subDirs) { mixin(S_TRACE);
  2064. if (0 == icmp(dir.name, s)) return false;
  2065. }
  2066. return true;
  2067. }));
  2068. .forceFocus(_dirTree, false);
  2069. refreshDirTree();
  2070. itm = findDirTree(sub.path);
  2071. _dirTree.setSelection([itm]);
  2072. updateDirSel();
  2073. _areaDirEdit.startEdit();
  2074. }
  2075. void edit() { mixin(S_TRACE);
  2076. int index = _areas.getSelectionIndex();
  2077. if (index == -1) return;
  2078. if (cast(Summary)_areas.getItem(index).getData()) { mixin(S_TRACE);
  2079. editSummary();
  2080. } else { mixin(S_TRACE);
  2081. openAreaScene(true);
  2082. }
  2083. }
  2084. @property
  2085. bool canEdit() { mixin(S_TRACE);
  2086. return _areas.getSelectionIndex() != -1;
  2087. }
  2088. @property
  2089. bool canReNumbering() { return !_readOnly && (showSummary ? 1 : 0) <= _areas.getSelectionIndex(); }
  2090. void reNumberingAll() { mixin(S_TRACE);
  2091. if (_readOnly) return;
  2092. auto undo = new UndoIDs(this, _comm, _summ);
  2093. bool reNum = false;
  2094. reNum |= reNumberingAreaImpl(0, 1);
  2095. reNum |= reNumberingBattleImpl(0, 1);
  2096. reNum |= reNumberingPackageImpl(0, 1);
  2097. if (reNum) _undo ~= undo;
  2098. }
  2099. void reNumberingArea(int index, ulong newId) { mixin(S_TRACE);
  2100. if (_readOnly) return;
  2101. auto undo = new UndoIDs(this, _comm, _summ);
  2102. bool reNum = reNumberingAreaImpl(index, newId);
  2103. if (reNum) _undo ~= undo;
  2104. }
  2105. void reNumberingBattle(int index, ulong newId) { mixin(S_TRACE);
  2106. if (_readOnly) return;
  2107. auto undo = new UndoIDs(this, _comm, _summ);
  2108. bool reNum = reNumberingBattleImpl(index, newId);
  2109. if (reNum) _undo ~= undo;
  2110. }
  2111. void reNumberingPackage(int index, ulong newId) { mixin(S_TRACE);
  2112. if (_readOnly) return;
  2113. auto undo = new UndoIDs(this, _comm, _summ);
  2114. bool reNum = reNumberingPackageImpl(index, newId);
  2115. if (reNum) _undo ~= undo;
  2116. }
  2117. private ulong[] reNumBef(A)(A[] arr, int index) { mixin(S_TRACE);
  2118. ulong[] oldIDs;
  2119. for (size_t i = index; i < arr.length; i++) { mixin(S_TRACE);
  2120. oldIDs ~= arr[i].id;
  2121. ulong ni = ulong.max - arr.length + i;
  2122. _summ.useCounter.change(A.toID(arr[i].id), A.toID(ni));
  2123. arr[i].id = ni;
  2124. }
  2125. return oldIDs;
  2126. }
  2127. private bool reNumberingImpl(A)(int index, ulong newId, A[] arr) { mixin(S_TRACE);
  2128. if (_readOnly) return false;
  2129. if (index < 0 || arr.length <= index) return false;
  2130. if (newId == 0) return false;
  2131. if (index > 0 && arr[index - 1].id >= newId) return false;
  2132. auto oldIDs = reNumBef(arr, index);
  2133. bool reNum = false;
  2134. for (size_t i = index; i < arr.length; i++) { mixin(S_TRACE);
  2135. _summ.useCounter.change(A.toID(arr[i].id), A.toID(newId));
  2136. arr[i].id = newId;
  2137. if (oldIDs[i - index] != newId) { mixin(S_TRACE);
  2138. callRefArea(arr[i]);
  2139. reNum = true;
  2140. }
  2141. newId++;
  2142. }
  2143. refreshIDs(false);
  2144. return reNum;
  2145. }
  2146. private bool reNumberingAreaImpl(int index, ulong newId) { mixin(S_TRACE);
  2147. if (_readOnly) return false;
  2148. return reNumberingImpl(index, newId, _summ.areas);
  2149. }
  2150. private bool reNumberingBattleImpl(int index, ulong newId) { mixin(S_TRACE);
  2151. if (_readOnly) return false;
  2152. return reNumberingImpl(index, newId, _summ.battles);
  2153. }
  2154. private bool reNumberingPackageImpl(int index, ulong newId) { mixin(S_TRACE);
  2155. if (_readOnly) return false;
  2156. return reNumberingImpl(index, newId, _summ.packages);
  2157. }
  2158. void reNumbering() { mixin(S_TRACE);
  2159. if (_readOnly) return;
  2160. if (!_summ) return;
  2161. ulong id;
  2162. TypeInfo type;
  2163. getSelectionInfo(id, type);
  2164. if (id <= 0) return;
  2165. int index = toIndexFrom(_summ, id, type);
  2166. _incSearch.close();
  2167. if (type is typeid(Area)) { mixin(S_TRACE);
  2168. auto dlg = new ReNumDialog!(Area)(_prop, _areas.getShell(), _summ.areas[index],
  2169. index == 0 ? 1 : _summ.areas[index - 1].id + 1);
  2170. if (dlg.open()) { mixin(S_TRACE);
  2171. _incSearch.close();
  2172. reNumberingArea(index, dlg.newId);
  2173. }
  2174. _comm.refreshToolBar();
  2175. return;
  2176. }
  2177. if (type is typeid(Battle)) { mixin(S_TRACE);
  2178. auto dlg = new ReNumDialog!(Battle)(_prop, _areas.getShell(), _summ.battles[index],
  2179. index == 0 ? 1 : _summ.battles[index - 1].id + 1);
  2180. if (dlg.open()) { mixin(S_TRACE);
  2181. _incSearch.close();
  2182. reNumberingBattle(index, dlg.newId);
  2183. }
  2184. _comm.refreshToolBar();
  2185. return;
  2186. }
  2187. if (type is typeid(Package)) { mixin(S_TRACE);
  2188. auto dlg = new ReNumDialog!(Package)(_prop, _areas.getShell(), _summ.packages[index],
  2189. index == 0 ? 1 : _summ.packages[index - 1].id + 1);
  2190. if (dlg.open()) { mixin(S_TRACE);
  2191. _incSearch.close();
  2192. reNumberingPackage(index, dlg.newId);
  2193. }
  2194. _comm.refreshToolBar();
  2195. return;
  2196. }
  2197. }
  2198. private void editSummary() { mixin(S_TRACE);
  2199. editSummary(_areas);
  2200. }
  2201. private SummaryDialog _summDlg = null;
  2202. void editSummary(Composite parent) { mixin(S_TRACE);
  2203. if (!_summ) return;
  2204. if (_summDlg) { mixin(S_TRACE);
  2205. _summDlg.active();
  2206. return;
  2207. }
  2208. _summDlg = new SummaryDialog(_comm, _prop, parent.getShell(), _summ, _readOnly == SWT.READ_ONLY);
  2209. _summDlg.applyEvent ~= { mixin(S_TRACE);
  2210. storeEdit(0UL, null);
  2211. };
  2212. _summDlg.appliedEvent ~= { mixin(S_TRACE);
  2213. if (showSummary) refresh();
  2214. updateAreaImage();
  2215. };
  2216. _summDlg.closeEvent ~= { mixin(S_TRACE);
  2217. _summDlg = null;
  2218. };
  2219. _summDlg.open();
  2220. }
  2221. @property
  2222. Control table() { mixin(S_TRACE);
  2223. return _areas;
  2224. }
  2225. @property
  2226. Control panel() { mixin(S_TRACE);
  2227. return _dirMode ? _areas.getParent().getParent() : _areas;
  2228. }
  2229. @property
  2230. string statusLine() {return _statusLine;}
  2231. void refresh() { mixin(S_TRACE);
  2232. refreshAreas();
  2233. }
  2234. @property
  2235. void summary(Summary summ) { mixin(S_TRACE);
  2236. _summ = summ;
  2237. _dirs = null;
  2238. _dir = "";
  2239. constructDirTree(false);
  2240. refreshAreas();
  2241. _comm.refreshToolBar();
  2242. }
  2243. /// ??????????????????????
  2244. void createArea() { mixin(S_TRACE);
  2245. if (_readOnly) return;
  2246. ulong[] a, b, p;
  2247. saveIDs(_summ, a, b, p);
  2248. auto area = new Area(_summ.newAreaId, _prop.msgs.areaNew);
  2249. if (_dirMode) area.dirName = _dir;
  2250. auto bgImages = createBgImages(_comm.skin, _prop.var.etc.bgImagesDefault);
  2251. foreach (bg; bgImages) { mixin(S_TRACE);
  2252. area.append(bg);
  2253. }
  2254. auto tree = new EventTree(_prop.msgs.enterTree);
  2255. tree.enter = true;
  2256. area.add(tree);
  2257. _summ.add(area);
  2258. storeInsert(area.id, typeid(Area), a, b, p);
  2259. int index = _summ.areas.length - 1;
  2260. addAreaItem(index);
  2261. auto sel = selArea(index);
  2262. sort();
  2263. _areas.showSelection();
  2264. _comm.refArea.call(area);
  2265. if (sel) _areasEdit.startEdit();
  2266. refreshStatusLine();
  2267. _comm.refreshToolBar();
  2268. }
  2269. /// ??????????????????????
  2270. void createBattle() { mixin(S_TRACE);
  2271. if (_readOnly) return;
  2272. ulong[] a, b, p;
  2273. saveIDs(_summ, a, b, p);
  2274. auto btl = new Battle(_summ.newBattleId, _prop.msgs.battleNew, _comm.skin.defBattle);
  2275. if (_dirMode) btl.dirName = _dir;
  2276. _summ.add(btl);
  2277. storeInsert(btl.id, typeid(Battle), a, b, p);
  2278. int index = _summ.battles.length - 1;
  2279. addBattleItem(index);
  2280. auto sel = selBattle(index);
  2281. sort();
  2282. _areas.showSelection();
  2283. _comm.refBattle.call(btl);
  2284. if (sel) _areasEdit.startEdit();
  2285. refreshStatusLine();
  2286. _comm.refreshToolBar();
  2287. }
  2288. /// ????????????????????????
  2289. void createPackage() { mixin(S_TRACE);
  2290. if (_readOnly) return;
  2291. createPackage(null);
  2292. }
  2293. /// ditto
  2294. ulong createPackage(Content baseStart) { mixin(S_TRACE);
  2295. if (_readOnly) return 0UL;
  2296. ulong[] a, b, p;
  2297. saveIDs(_summ, a, b, p);
  2298. auto pkg = new Package(_summ.newPackageId, baseStart ? baseStart.name : _prop.msgs.packageNew);
  2299. if (_dirMode) pkg.dirName = _dir;
  2300. EventTree et;
  2301. if (baseStart) { mixin(S_TRACE);
  2302. et = new EventTree(baseStart);
  2303. et.name = _prop.msgs.packageTree;
  2304. } else { mixin(S_TRACE);
  2305. et = new EventTree(_prop.msgs.packageTree);
  2306. }
  2307. pkg.add(et);
  2308. _summ.add(pkg);
  2309. storeInsert(pkg.id, typeid(Package), a, b, p);
  2310. int index = _summ.packages.length - 1;
  2311. addPackageItem(index);
  2312. auto sel = selPackage(index);
  2313. sort();
  2314. _areas.showSelection();
  2315. _comm.refPackage.call(pkg);
  2316. if (sel) _areasEdit.startEdit();
  2317. refreshStatusLine();
  2318. _comm.refreshToolBar();
  2319. return pkg.id;
  2320. }
  2321. @property
  2322. private bool selArea(int index) { mixin(S_TRACE);
  2323. return select(_summ.areas[index]);
  2324. }
  2325. @property
  2326. private bool selBattle(int index) { mixin(S_TRACE);
  2327. return select(_summ.battles[index]);
  2328. }
  2329. @property
  2330. private bool selPackage(int index) { mixin(S_TRACE);
  2331. return select(_summ.packages[index]);
  2332. }
  2333. void selectSummary() { mixin(S_TRACE);
  2334. if (!_summ) return;
  2335. if (_dirMode) { mixin(S_TRACE);
  2336. if (!showTreeSummary) return;
  2337. _dirTree.setSelection([_dirTree.getItem(0)]);
  2338. } else { mixin(S_TRACE);
  2339. if (!showSummary) return;
  2340. _areas.select(0);
  2341. }
  2342. }
  2343. @property
  2344. private bool showTreeSummary() {
  2345. auto itm = _dirTree.getItem(0);
  2346. return cast(Summary)itm.getData() !is null;
  2347. }
  2348. @property
  2349. private TreeItem rootDir() {
  2350. return _dirTree.getItem(showTreeSummary ? 1 : 0);
  2351. }
  2352. bool select(AbstractArea a) { mixin(S_TRACE);
  2353. if (_dirMode) { mixin(S_TRACE);
  2354. _dirTree.setSelection([findDirTree(a.dirName)]);
  2355. updateDirSel();
  2356. }
  2357. int i = cCountUntil!("a.getData() is b")(_areas.getItems(), a);
  2358. if (0 <= i) { mixin(S_TRACE);
  2359. _areas.select(i);
  2360. _areas.showSelection();
  2361. _comm.refreshToolBar();
  2362. return true;
  2363. }
  2364. return false;
  2365. }
  2366. private void select(AbstractArea[] areas) { mixin(S_TRACE);
  2367. if (!areas.length) return;
  2368. select(areas[$-1]);
  2369. foreach (a; areas) {
  2370. int i = cCountUntil!("a.getData() is b")(_areas.getItems(), a);
  2371. if (0 <= i) { mixin(S_TRACE);
  2372. _areas.select(i);
  2373. }
  2374. }
  2375. _comm.refreshToolBar();
  2376. }
  2377. @property
  2378. bool canOpenAreaScene() { mixin(S_TRACE);
  2379. return (showSummary ? 1 : 0) <= _areas.getSelectionIndex();
  2380. }
  2381. @property
  2382. bool canOpenAreaEvent() { mixin(S_TRACE);
  2383. return (showSummary ? 1 : 0) <= _areas.getSelectionIndex();
  2384. }
  2385. void openAreaScene(bool shellActivate) { mixin(S_TRACE);
  2386. foreach (area; getSelectionAreas()) { mixin(S_TRACE);
  2387. if (area) { mixin(S_TRACE);
  2388. auto a = cast(Area) area;
  2389. if (a) { mixin(S_TRACE);
  2390. openAreaSceneImpl(a, shellActivate);
  2391. }
  2392. auto b = cast(Battle) area;
  2393. if (b) { mixin(S_TRACE);
  2394. openAreaSceneImpl(b, shellActivate);
  2395. }
  2396. auto p = cast(Package) area;
  2397. if (p) { mixin(S_TRACE);
  2398. _comm.openArea(_prop, _summ, p, shellActivate);
  2399. }
  2400. }
  2401. }
  2402. }
  2403. void openAreaScene(int x, int y, bool shellActivate) { mixin(S_TRACE);
  2404. auto itm = _areas.getItem(new Point(x, y));
  2405. if (itm) { mixin(S_TRACE);
  2406. _areas.setSelection([itm]);
  2407. openAreaScene(cast(AbstractArea) itm.getData(), shellActivate);
  2408. } else { mixin(S_TRACE);
  2409. openAreaScene(shellActivate);
  2410. }
  2411. }
  2412. void openAreaEvent(int x, int y, bool shellActivate) { mixin(S_TRACE);
  2413. auto itm = _areas.getItem(new Point(x, y));
  2414. if (itm) { mixin(S_TRACE);
  2415. _areas.setSelection([itm]);
  2416. openAreaEvent(cast(AbstractArea) itm.getData(), shellActivate);
  2417. } else { mixin(S_TRACE);
  2418. openAreaEvent(shellActivate);
  2419. }
  2420. }
  2421. void openAreaEvent(bool shellActivate) { mixin(S_TRACE);
  2422. foreach (area; getSelectionAreas()) { mixin(S_TRACE);
  2423. openAreaEvent(area, shellActivate);
  2424. }
  2425. }
  2426. void openAreaScene(AbstractArea area, bool shellActivate) { mixin(S_TRACE);
  2427. auto a = cast(Area) area;
  2428. if (a) { mixin(S_TRACE);
  2429. openAreaSceneImpl(a, shellActivate);
  2430. return;
  2431. }
  2432. auto b = cast(Battle) area;
  2433. if (b) { mixin(S_TRACE);
  2434. openAreaSceneImpl(b, shellActivate);
  2435. return;
  2436. }
  2437. auto p = cast(Package) area;
  2438. if (p) { mixin(S_TRACE);
  2439. _comm.openArea(_prop, _summ, p, shellActivate);
  2440. return;
  2441. }
  2442. }
  2443. void openAreaEvent(AbstractArea area, bool shellActivate) { mixin(S_TRACE);
  2444. auto a = cast(Area) area;
  2445. if (a) { mixin(S_TRACE);
  2446. openAreaEventImpl(a, shellActivate);
  2447. return;
  2448. }
  2449. auto b = cast(Battle) area;
  2450. if (b) { mixin(S_TRACE);
  2451. openAreaEventImpl(b, shellActivate);
  2452. return;
  2453. }
  2454. auto p = cast(Package) area;
  2455. if (p) { mixin(S_TRACE);
  2456. _comm.openArea(_prop, _summ, p, shellActivate);
  2457. return;
  2458. }
  2459. }
  2460. void openAreaSceneImpl(A)(A a, bool shellActivate) { mixin(S_TRACE);
  2461. if (!_comm.singleWindowMode(_prop) || _prop.var.etc.bindSceneWithEvent) { mixin(S_TRACE);
  2462. _comm.openArea(_prop, _summ, a, shellActivate);
  2463. } else { mixin(S_TRACE);
  2464. _comm.openAreaScene(_prop, _summ, a, shellActivate);
  2465. }
  2466. }
  2467. void openAreaEventImpl(A)(A a, bool shellActivate) { mixin(S_TRACE);
  2468. if (!_comm.singleWindowMode(_prop) || _prop.var.etc.bindSceneWithEvent) { mixin(S_TRACE);
  2469. auto w = _comm.openArea(_prop, _summ, a, shellActivate);
  2470. w.selectEventView();
  2471. } else { mixin(S_TRACE);
  2472. _comm.openAreaEvent(_prop, _summ, a, shellActivate);
  2473. }
  2474. }
  2475. void openAreaScene(ulong id, bool shellActivate) { mixin(S_TRACE);
  2476. openAreaSceneImpl(_summ.area(id), shellActivate);
  2477. }
  2478. void openAreaEvent(ulong id, bool shellActivate) { mixin(S_TRACE);
  2479. openAreaEventImpl(_summ.area(id), shellActivate);
  2480. }
  2481. void openBattleScene(ulong id, bool shellActivate) { mixin(S_TRACE);
  2482. openAreaSceneImpl(_summ.battle(id), shellActivate);
  2483. }
  2484. void openBattleEvent(ulong id, bool shellActivate) { mixin(S_TRACE);
  2485. openAreaEventImpl(_summ.area(id), shellActivate);
  2486. }
  2487. void openPackage(ulong id, bool shellActivate) { mixin(S_TRACE);
  2488. _comm.openArea(_prop, _summ, _summ.cwPackage(id), shellActivate);
  2489. }
  2490. private bool canUdImpl(int index1, int index2) { mixin(S_TRACE);
  2491. if (_readOnly) return false;
  2492. if (!_summ) return false;
  2493. if (_areas.getItemCount() != countAllAreas) return false;
  2494. if (index1 < (showSummary ? 1 : 0) || _areas.getItemCount() <= index1) return false;
  2495. if (index2 < (showSummary ? 1 : 0) || _areas.getItemCount() <= index2) return false;
  2496. auto area1 = cast(AbstractArea)_areas.getItem(index1).getData();
  2497. auto area2 = cast(AbstractArea)_areas.getItem(index2).getData();
  2498. if (cast(Area) area1 && cast(Area) area2) { mixin(S_TRACE);
  2499. return canUdImpl2!Area(area1, area2);
  2500. }
  2501. if (cast(Battle) area1 && cast(Battle) area2) { mixin(S_TRACE);
  2502. return canUdImpl2!Battle(area1, area2);
  2503. }
  2504. if (cast(Package) area1 && cast(Package) area2) { mixin(S_TRACE);
  2505. return canUdImpl2!Package(area1, area2);
  2506. }
  2507. return false;
  2508. }
  2509. private bool canUdImpl2(A)(AbstractArea area1, AbstractArea area2) { mixin(S_TRACE);
  2510. if (_readOnly) return false;
  2511. auto a1 = cast(A)area1;
  2512. auto a2 = cast(A)area2;
  2513. return a1 && a2;
  2514. }
  2515. private void udImpl(int index1, int index2) { mixin(S_TRACE);
  2516. if (_readOnly) return;
  2517. if (!canUdImpl(index1, index2)) return;
  2518. auto area1 = cast(AbstractArea)_areas.getItem(index1).getData();
  2519. auto area2 = cast(AbstractArea)_areas.getItem(index2).getData();
  2520. if (cast(Area) area1 && cast(Area) area2) { mixin(S_TRACE);
  2521. udImpl2!Area(area1, area2);
  2522. }
  2523. if (cast(Battle) area1 && cast(Battle) area2) { mixin(S_TRACE);
  2524. udImpl2!Battle(area1, area2);
  2525. }
  2526. if (cast(Package) area1 && cast(Package) area2) { mixin(S_TRACE);
  2527. udImpl2!Package(area1, area2);
  2528. }
  2529. _comm.refreshToolBar();
  2530. }
  2531. private void udImpl2(A)(AbstractArea area1, AbstractArea area2) { mixin(S_TRACE);
  2532. if (_readOnly) return;
  2533. assert (_areas.getSortColumn() is null || _areas.getSortColumn() is _idSorter.column);
  2534. auto a1 = cast(A)area1;
  2535. auto a2 = cast(A)area2;
  2536. if (!a1 || !a2) return;
  2537. int i1 = _summ.indexOf(a1);
  2538. int i2 = _summ.indexOf(a2);
  2539. if (_dirMode) { mixin(S_TRACE);
  2540. // ???????????????
  2541. static if (is(A:Area)) {
  2542. auto array = _summ.areas;
  2543. } else static if (is(A:Battle)) {
  2544. auto array = _summ.battles;
  2545. } else static if (is(A:Package)) {
  2546. auto array = _summ.packages;
  2547. } else static assert (0);
  2548. int lastIndex = indexOf(a1);
  2549. ATUndo[] undos;
  2550. do { mixin(S_TRACE);
  2551. undos ~= new UndoSwap(this, _comm, _summ, indexFrom!A(_summ, i1), indexFrom!A(_summ, i2));
  2552. a2 = array[i2];
  2553. _summ.swap!A(i1, i2);
  2554. int mv = i2 - i1;
  2555. i1 += mv;
  2556. i2 += mv;
  2557. } while (0 != icmp(a1.dirName, a2.dirName));
  2558. _undo ~= new ATUndoArr(undos);
  2559. } else { mixin(S_TRACE);
  2560. storeSwap(indexFrom!A(_summ, i1), indexFrom!A(_summ, i2));
  2561. _summ.swap!A(i1, i2);
  2562. }
  2563. int m = showSummary ? 1 : 0;
  2564. refreshAreas();
  2565. select(a1);
  2566. _areas.showSelection();
  2567. static if (is(A : Area)) {
  2568. _comm.refArea.call(a1);
  2569. _comm.refArea.call(a2);
  2570. } else static if (is(A : Battle)) {
  2571. _comm.refBattle.call(a1);
  2572. _comm.refBattle.call(a2);
  2573. } else static if (is(A : Package)) {
  2574. _comm.refPackage.call(a1);
  2575. _comm.refPackage.call(a2);
  2576. } else static assert (0);
  2577. }
  2578. @property
  2579. bool canUp() { mixin(S_TRACE);
  2580. if (_readOnly) return false;
  2581. if (!_summ) return false;
  2582. if (_areas.getItemCount() != countAllAreas) return false;
  2583. if (!(_areas.getSortColumn() is null || _areas.getSortColumn() is _idSorter.column)) return false;
  2584. if (!_areas.isFocusControl()) return false;
  2585. int sel = _areas.getSelectionIndex();
  2586. if (sel < (showSummary ? 1 : 0)) return false;
  2587. return canUdImpl(sel, sel - 1);
  2588. }
  2589. @property
  2590. bool canDown() { mixin(S_TRACE);
  2591. if (_readOnly) return false;
  2592. if (!_summ) return false;
  2593. if (_areas.getItemCount() != countAllAreas) return false;
  2594. if (!(_areas.getSortColumn() is null || _areas.getSortColumn() is _idSorter.column)) return false;
  2595. if (!_areas.isFocusControl()) return false;
  2596. int sel = _areas.getSelectionIndex();
  2597. if (sel < (showSummary ? 1 : 0)) return false;
  2598. return canUdImpl(sel, sel + 1);
  2599. }
  2600. void up() { mixin(S_TRACE);
  2601. if (_readOnly) return;
  2602. _parent.setRedraw(false);
  2603. scope (exit) _parent.setRedraw(true);
  2604. if (!canUp) return;
  2605. if (!_areas.isFocusControl()) return;
  2606. if (_areaDirEdit) _areaDirEdit.cancel();
  2607. _areasEdit.cancel();
  2608. int sel = _areas.getSelectionIndex();
  2609. if (sel < (showSummary ? 1 : 0)) return;
  2610. udImpl(sel, sel - 1);
  2611. }
  2612. void down() { mixin(S_TRACE);
  2613. if (_readOnly) return;
  2614. _parent.setRedraw(false);
  2615. scope (exit) _parent.setRedraw(true);
  2616. if (!canDown) return;
  2617. if (!_areas.isFocusControl()) return;
  2618. if (_areaDirEdit) _areaDirEdit.cancel();
  2619. _areasEdit.cancel();
  2620. int sel = _areas.getSelectionIndex();
  2621. if (sel < (showSummary ? 1 : 0)) return;
  2622. udImpl(sel, sel + 1);
  2623. }
  2624. @property
  2625. bool canSetStartArea() {
  2626. if (_readOnly) return false;
  2627. if (auto a = cast(Area)getSelectionArea()) {
  2628. return _summ.startArea != a.id;
  2629. }
  2630. return false;
  2631. }
  2632. void setStartArea() {
  2633. if (_readOnly) return;
  2634. if (auto a = cast(Area)getSelectionArea()) {
  2635. storeEdit(0UL, null);
  2636. _summ.startArea = a.id;
  2637. updateAreaImage();
  2638. }
  2639. }
  2640. @property
  2641. private AbstractArea[] dirAreas() { mixin(S_TRACE);
  2642. AbstractArea[] areas;
  2643. auto path = _dir == "" ? _dir : _dir ~ "\\";
  2644. void put(AbstractArea area) { mixin(S_TRACE);
  2645. if (istartsWith(area.name, path)) { mixin(S_TRACE);
  2646. areas ~= area;
  2647. }
  2648. }
  2649. foreach (a; _summ.areas) put(a);
  2650. foreach (a; _summ.battles) put(a);
  2651. foreach (a; _summ.packages) put(a);
  2652. return areas;
  2653. }
  2654. override {
  2655. void cut(SelectionEvent se) { mixin(S_TRACE);
  2656. _parent.setRedraw(false);
  2657. scope (exit) _parent.setRedraw(true);
  2658. copy(se);
  2659. del(se);
  2660. }
  2661. void copy(SelectionEvent se) { mixin(S_TRACE);
  2662. _parent.setRedraw(false);
  2663. scope (exit) _parent.setRedraw(true);
  2664. if (_dirTree && _dirTree.isFocusControl()) { mixin(S_TRACE);
  2665. auto path = _dir == "" ? _dir : _dir ~ "\\";
  2666. auto areas = dirAreas;
  2667. XNode doc;
  2668. string parentPath = _dir == "" ? _prop.msgs.areaDirRoot : _dir.split("\\")[$ - 1];
  2669. if (areas.length) { mixin(S_TRACE);
  2670. doc = areasToNode(parentPath, _dir, areas, new XMLOption(_prop.sys), _summ.id);
  2671. } else {
  2672. doc = XNode.create("Table");
  2673. doc.newAttr("summaryId", _summ.id);
  2674. }
  2675. // ?????????
  2676. auto parent = cast(DirTree)findDirTree(_dir).getData();
  2677. void recurse(DirTree dir) { mixin(S_TRACE);
  2678. auto p = dir.path;
  2679. if (0 == icmp(p, _dir)) { mixin(S_TRACE);
  2680. doc.newElement("TablePath", parentPath);
  2681. } else { mixin(S_TRACE);
  2682. doc.newElement("TablePath", parentPath ~ "\\" ~ p[path.length .. $]);
  2683. }
  2684. foreach (sub; dir.subDirs) recurse(sub);
  2685. }
  2686. recurse(parent);
  2687. XMLtoCB(_prop, _comm.clipboard, doc.text);
  2688. _comm.refreshToolBar();
  2689. } else { mixin(S_TRACE);
  2690. auto areas = getSelectionAreas();
  2691. if (areas.length) { mixin(S_TRACE);
  2692. auto doc = areasToNode("", _dir, areas, new XMLOption(_prop.sys), _summ.id);
  2693. XMLtoCB(_prop, _comm.clipboard, doc.text);
  2694. _comm.refreshToolBar();
  2695. }
  2696. }
  2697. }
  2698. void paste(SelectionEvent se) { mixin(S_TRACE);
  2699. _parent.setRedraw(false);
  2700. scope (exit) _parent.setRedraw(true);
  2701. auto c = CBtoXML(_comm.clipboard);
  2702. if (c) { mixin(S_TRACE);
  2703. try { mixin(S_TRACE);
  2704. auto node = XNode.parse(c);
  2705. pasteImpl(node);
  2706. } catch (Exception e) { mixin (S_TRACE);
  2707. debugln(e);
  2708. }
  2709. }
  2710. }
  2711. void del(SelectionEvent se) { mixin(S_TRACE);
  2712. _parent.setRedraw(false);
  2713. scope (exit) _parent.setRedraw(true);
  2714. AbstractArea[] areas;
  2715. if (_dirTree && _dirTree.isFocusControl()) {
  2716. auto path = _dir == "" ? _dir : _dir ~ "\\";
  2717. void put(AbstractArea area) { mixin(S_TRACE);
  2718. if (istartsWith(area.name, path)) { mixin(S_TRACE);
  2719. areas ~= area;
  2720. }
  2721. }
  2722. foreach (a; _summ.areas) put(a);
  2723. foreach (a; _summ.battles) put(a);
  2724. foreach (a; _summ.packages) put(a);
  2725. } else {
  2726. areas = getSelectionAreas();
  2727. }
  2728. ATUndo[] undos;
  2729. foreach (area; areas) { mixin(S_TRACE);
  2730. ulong id;
  2731. TypeInfo type;
  2732. getInfoFromArea(area, id, type);
  2733. undos ~= new UndoInsertDelete(this, _comm, _summ, id, type, false, [], [], []);
  2734. _summ.remove(area);
  2735. if (cast(Area) area) { mixin(S_TRACE);
  2736. _comm.delArea.call(cast(Area) area);
  2737. } else if (cast(Battle) area) { mixin(S_TRACE);
  2738. _comm.delBattle.call(cast(Battle) area);
  2739. } else { mixin(S_TRACE);
  2740. assert (cast(Package) area);
  2741. _comm.delPackage.call(cast(Package) area);
  2742. }
  2743. }
  2744. if (!undos.length) storeEmpty();
  2745. if (_dirTree && _dirTree.isFocusControl()) { mixin(S_TRACE);
  2746. auto itm = findDirTree(_dir).getParentItem();
  2747. delDirTree(_dir);
  2748. _dirTree.setSelection([itm]);
  2749. updateDirSel();
  2750. }
  2751. if (undos.length) { mixin(S_TRACE);
  2752. refreshAreas();
  2753. if (_flags) _flags.refresh();
  2754. _comm.refUseCount.call();
  2755. refreshStatusLine();
  2756. _comm.refreshToolBar();
  2757. _undo ~= new ATUndoArr(undos);
  2758. }
  2759. }
  2760. void clone(SelectionEvent se) { mixin(S_TRACE);
  2761. _parent.setRedraw(false);
  2762. scope (exit) _parent.setRedraw(true);
  2763. _comm.clipboard.memoryMode = true;
  2764. scope (exit) _comm.clipboard.memoryMode = false;
  2765. copy(se);
  2766. if (_dirTree && _dirTree.isFocusControl()) { mixin(S_TRACE);
  2767. // ??????????????????????????
  2768. auto sels = _dirTree.getSelection();
  2769. assert (sels.length);
  2770. auto itm = sels[0].getParentItem();
  2771. if (itm) {
  2772. _dirTree.setSelection([itm]);
  2773. _dir = (cast(DirTree)itm.getData()).path;
  2774. }
  2775. }
  2776. paste(se);
  2777. }
  2778. @property
  2779. bool canDoTCPD() { mixin(S_TRACE);
  2780. return _summ && (_areas.isFocusControl() || (_dirTree && _dirTree.isFocusControl()));
  2781. }
  2782. @property
  2783. bool canDoT() { mixin(S_TRACE);
  2784. return !_readOnly && canDoC && canDoD;
  2785. }
  2786. @property
  2787. bool canDoC() { mixin(S_TRACE);
  2788. if (_dirTree && _dirTree.isFocusControl()) { mixin(S_TRACE);
  2789. auto sels = _dirTree.getSelection();
  2790. return sels.length && cast(DirTree)sels[0].getData();
  2791. } else { mixin(S_TRACE);
  2792. return (showSummary ? 1 : 0) <= _areas.getSelectionIndex();
  2793. }
  2794. }
  2795. @property
  2796. bool canDoP() { mixin(S_TRACE);
  2797. return !_readOnly && _summ !is null && CBisXML(_comm.clipboard);
  2798. }
  2799. @property
  2800. bool canDoClone() { mixin(S_TRACE);
  2801. return !_readOnly && canDoC;
  2802. }
  2803. @property
  2804. bool canDoD() { mixin(S_TRACE);
  2805. if (_readOnly) return false;
  2806. if (_dirTree && _dirTree.isFocusControl()) { mixin(S_TRACE);
  2807. auto sels = _dirTree.getSelection();
  2808. if (!sels.length) return false;
  2809. auto dir = cast(DirTree)sels[0].getData();
  2810. return dir && dir.parent !is null;
  2811. } else { mixin(S_TRACE);
  2812. return (showSummary ? 1 : 0) <= _areas.getSelectionIndex();
  2813. }
  2814. }
  2815. }
  2816. private void pasteImpl(ref XNode node) { mixin(S_TRACE);
  2817. if (_readOnly) return;
  2818. _parent.setRedraw(false);
  2819. scope (exit) _parent.setRedraw(true);
  2820. bool sameSummary;
  2821. auto ver = new XMLInfo(_prop.sys, LATEST_VERSION);
  2822. bool fromTable;
  2823. auto areas = createAreasFromNode(node, _summ.id, sameSummary, fromTable, ver);
  2824. ATUndo[] undos;
  2825. AbstractArea sel = null;
  2826. auto existsDirs = new HashSet!string;
  2827. void eRecurse(DirTree dir) { mixin(S_TRACE);
  2828. existsDirs.add(dir.path.toLower());
  2829. foreach (sub; dir.subDirs) eRecurse(sub);
  2830. }
  2831. if (_dirMode) eRecurse(_dirs);
  2832. string renameDir(string dir) { mixin(S_TRACE);
  2833. if (dir == "") return dir;
  2834. // ???????????????(2)?????
  2835. auto dirs = dir.split("\\");
  2836. auto firstDir = dirs[0];
  2837. firstDir = createNewName(firstDir, (s) { mixin(S_TRACE);
  2838. if (_dir != "") s = _dir ~ "\\" ~ s;
  2839. return !existsDirs.contains(s.toLower());
  2840. });
  2841. return ([firstDir] ~ dirs[1..$]).join("\\");
  2842. }
  2843. string lastPutDir = "";
  2844. if (_dirMode) {
  2845. auto curItm = findDirTree(_dir);
  2846. auto curDir = cast(DirTree)curItm.getData();
  2847. node.onTag["TablePath"] = (ref XNode node) { mixin(S_TRACE);
  2848. auto dir = renameDir(node.value);
  2849. if (dir == "") return;
  2850. if (!undos.length) undos ~= new UndoIDs(this, _comm, _summ);
  2851. lastPutDir = putDir(curDir, dir);
  2852. };
  2853. node.parse();
  2854. }
  2855. foreach (area; areas) { mixin(S_TRACE);
  2856. sel = area;
  2857. if (_dirMode) { mixin(S_TRACE);
  2858. if (fromTable) { mixin(S_TRACE);
  2859. // ???????????????
  2860. area.dirName = renameDir(area.dirName);
  2861. if (_dir != "") { mixin(S_TRACE);
  2862. area.name = _dir ~ "\\" ~ area.name;
  2863. }
  2864. } else { mixin(S_TRACE);
  2865. area.dirName = _dir;
  2866. }
  2867. }
  2868. auto oldId = area.id;
  2869. ulong[] a, b, p;
  2870. saveIDs(_summ, a, b, p);
  2871. if (cast(Area)area) { mixin(S_TRACE);
  2872. _summ.add(cast(Area)area);
  2873. undos ~= new UndoInsertDelete(this, _comm, _summ, area.id, typeid(Area), true, a, b, p);
  2874. _comm.refArea.call(cast(Area)area);
  2875. if (sameSummary && !_summ.hasAreaId(oldId)) { mixin(S_TRACE);
  2876. _summ.useCounter.change(toAreaId(oldId), toAreaId(area.id));
  2877. }
  2878. } else if (cast(Battle)area) { mixin(S_TRACE);
  2879. _summ.add(cast(Battle) area);
  2880. undos ~= new UndoInsertDelete(this, _comm, _summ, area.id, typeid(Battle), true, a, b, p);
  2881. _comm.refBattle.call(cast(Battle)area);
  2882. if (sameSummary && !_summ.hasBattleId(oldId)) { mixin(S_TRACE);
  2883. _summ.useCounter.change(toBattleId(oldId), toBattleId(area.id));
  2884. }
  2885. } else if (cast(Package)area) { mixin(S_TRACE);
  2886. _summ.add(cast(Package) area);
  2887. undos ~= new UndoInsertDelete(this, _comm, _summ, area.id, typeid(Package), true, a, b, p);
  2888. _comm.refPackage.call(cast(Package)area);
  2889. if (sameSummary && !_summ.hasPackageId(oldId)) { mixin(S_TRACE);
  2890. _summ.useCounter.change(toPackageId(oldId), toPackageId(area.id));
  2891. }
  2892. } else assert (0);
  2893. }
  2894. if (lastPutDir != "" || sel) { mixin (S_TRACE);
  2895. if (_dirMode) {
  2896. constructDirTree(true);
  2897. }
  2898. refreshAreas();
  2899. }
  2900. if (sel) { mixin (S_TRACE);
  2901. sort();
  2902. if (_readOnly) { mixin (S_TRACE);
  2903. select(areas);
  2904. } else { mixin (S_TRACE);
  2905. select(sel);
  2906. }
  2907. if (_flags) _flags.refresh();
  2908. _comm.refUseCount.call();
  2909. refreshStatusLine();
  2910. _comm.refreshToolBar();
  2911. _undo ~= new ATUndoArr(undos);
  2912. }
  2913. if (_dirMode && !sel && lastPutDir != "") {
  2914. _dirTree.setSelection([findDirTree(lastPutDir)]);
  2915. updateDirSel();
  2916. }
  2917. }
  2918. private void delItem(in AbstractArea area) { mixin(S_TRACE);
  2919. if (_readOnly) return;
  2920. foreach (itm; _areas.getItems()) { mixin(S_TRACE);
  2921. if (itm.getData() is area) { mixin(S_TRACE);
  2922. itm.dispose();
  2923. break;
  2924. }
  2925. }
  2926. }
  2927. /// ????areas??????
  2928. /// ???????ID???????????
  2929. void addAreas(AbstractArea[] areas) {
  2930. if (_readOnly) return;
  2931. _parent.setRedraw(false);
  2932. scope (exit) _parent.setRedraw(true);
  2933. ATUndo[] undos;
  2934. AbstractArea sel = null;
  2935. foreach (area; areas) { mixin(S_TRACE);
  2936. sel = area;
  2937. ulong[] a, b, p;
  2938. saveIDs(_summ, a, b, p);
  2939. if (cast(Area)area) { mixin(S_TRACE);
  2940. _summ.add(cast(Area)area);
  2941. undos ~= new UndoInsertDelete(this, _comm, _summ, area.id, typeid(Area), true, a, b, p);
  2942. _comm.refArea.call(cast(Area)area);
  2943. } else if (cast(Battle)area) { mixin(S_TRACE);
  2944. _summ.add(cast(Battle) area);
  2945. undos ~= new UndoInsertDelete(this, _comm, _summ, area.id, typeid(Battle), true, a, b, p);
  2946. _comm.refBattle.call(cast(Battle)area);
  2947. } else if (cast(Package)area) { mixin(S_TRACE);
  2948. _summ.add(cast(Package) area);
  2949. undos ~= new UndoInsertDelete(this, _comm, _summ, area.id, typeid(Package), true, a, b, p);
  2950. _comm.refPackage.call(cast(Package)area);
  2951. } else assert (0);
  2952. }
  2953. if (sel) { mixin (S_TRACE);
  2954. if (_dirMode) {
  2955. constructDirTree(true);
  2956. }
  2957. refreshAreas();
  2958. }
  2959. if (sel) { mixin (S_TRACE);
  2960. sort();
  2961. select(sel);
  2962. if (_flags) _flags.refresh();
  2963. _comm.refUseCount.call();
  2964. refreshStatusLine();
  2965. _comm.refreshToolBar();
  2966. _undo ~= new ATUndoArr(undos);
  2967. }
  2968. }
  2969. @property
  2970. bool canUndo() { mixin(S_TRACE);
  2971. return !_readOnly && _undo.canUndo();
  2972. }
  2973. @property
  2974. bool canRedo() { mixin(S_TRACE);
  2975. return !_readOnly && _undo.canRedo();
  2976. }
  2977. void undo() { mixin(S_TRACE);
  2978. if (_readOnly) return;
  2979. _undo.undo();
  2980. _comm.refreshToolBar();
  2981. }
  2982. void redo() { mixin(S_TRACE);
  2983. if (_readOnly) return;
  2984. _undo.redo();
  2985. _comm.refreshToolBar();
  2986. }
  2987. void replaceID() { mixin(S_TRACE);
  2988. if (_readOnly) return;
  2989. auto area = getSelectionArea();
  2990. if (cast(Area)area) _comm.replaceID(toAreaId(area.id), true);
  2991. if (cast(Battle)area) _comm.replaceID(toBattleId(area.id), true);
  2992. if (cast(Package)area) _comm.replaceID(toPackageId(area.id), true);
  2993. }
  2994. @property
  2995. bool canReplaceID() { mixin(S_TRACE);
  2996. if (_readOnly) return false;
  2997. auto area = getSelectionArea();
  2998. return cast(Area)area || cast(Battle)area || cast(Package)area;
  2999. }
  3000. void doImport() { mixin(S_TRACE);
  3001. AbstractArea[] areas;
  3002. string[] paths;
  3003. if (_dirTree && _dirTree.isFocusControl()) { mixin(S_TRACE);
  3004. areas = dirAreas;
  3005. } else { mixin(S_TRACE);
  3006. areas = getSelectionAreas();
  3007. }
  3008. if (!areas.length) return;
  3009. foreach (area; areas) { mixin(S_TRACE);
  3010. paths ~= area.cwxPath(true);
  3011. }
  3012. _comm.doImport(_importTarget, _summ, paths);
  3013. }
  3014. @property
  3015. bool canDoImport() { mixin(S_TRACE);
  3016. if (_dirTree && _dirTree.isFocusControl()) { mixin(S_TRACE);
  3017. return _importTarget && dirAreas.length;
  3018. } else { mixin(S_TRACE);
  3019. return _importTarget && getSelectionAreas().length;
  3020. }
  3021. }
  3022. @property
  3023. bool isSelected() { return _areas.getSelectionIndex() != -1; }
  3024. @property
  3025. string[] openedCWXPath() { mixin(S_TRACE);
  3026. string[] r;
  3027. if (_summ && showSummary && 0 == _areas.getSelectionIndex()) { mixin(S_TRACE);
  3028. r ~= _summ.cwxPath(true);
  3029. }
  3030. foreach (area; getSelectionAreas()) {
  3031. r ~= cpaddattr(area.cwxPath(true), "shallow");
  3032. }
  3033. return r;
  3034. }
  3035. }