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

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

https://bitbucket.org/k4nagatsuki/cwxeditor
D | 1848 lines | 1713 code | 77 blank | 58 comment | 239 complexity | ec171a91f6617218784a7fa9676b6ac9 MD5 | raw file
Possible License(s): LGPL-2.1
  1. module cwx.editor.gui.dwt.flagtable;
  2. import cwx.summary;
  3. import cwx.flag;
  4. import cwx.utils;
  5. import cwx.usecounter;
  6. import cwx.path;
  7. import cwx.menu;
  8. import cwx.types;
  9. import cwx.system;
  10. import cwx.card;
  11. import cwx.event;
  12. import cwx.editor.gui.dwt.dutils;
  13. import cwx.editor.gui.dwt.dprops;
  14. import cwx.editor.gui.dwt.commons;
  15. import cwx.editor.gui.dwt.xmlbytestransfer;
  16. import cwx.editor.gui.dwt.absdialog;
  17. import cwx.editor.gui.dwt.centerlayout;
  18. import cwx.editor.gui.dwt.undo;
  19. import cwx.editor.gui.dwt.dmenu;
  20. import cwx.editor.gui.dwt.incsearch;
  21. import std.array;
  22. import std.ascii;
  23. import std.conv;
  24. import std.string;
  25. import std.exception;
  26. import org.eclipse.swt.all;
  27. import java.lang.all;
  28. /// ??????????????
  29. /// ??????10?????
  30. public class StepEditDialog : AbsDialog {
  31. private:
  32. Commons _comm;
  33. Props prop;
  34. Step _step;
  35. FlagDir dir;
  36. Text stepName;
  37. Combo stepInit;
  38. Text[] stepVals;
  39. void refreshWarning() { mixin(S_TRACE);
  40. string[] ws;
  41. if (prop.sys.isSystemVar(stepName.getText())) { mixin(S_TRACE);
  42. ws ~= .tryFormat(prop.msgs.warningSystemVarName, prop.sys.prefixSystemVarName);
  43. }
  44. warning = ws;
  45. }
  46. class ModValue : ModifyListener {
  47. private:
  48. int index;
  49. public:
  50. this(int index) { mixin(S_TRACE);
  51. this.index = index;
  52. }
  53. override void modifyText(ModifyEvent e) { mixin(S_TRACE);
  54. if (index < stepInit.getItemCount()) { mixin(S_TRACE);
  55. stepInit.setItem(index, (cast(Text) e.getSource()).getText());
  56. }
  57. }
  58. }
  59. class Dispose : DisposeListener {
  60. override void widgetDisposed(DisposeEvent e) { mixin(S_TRACE);
  61. _comm.delFlagAndStep.remove(&delStep);
  62. _comm.refScenario.remove(&refScenario);
  63. }
  64. }
  65. void delStep(Flag[] flag, Step[] step) { mixin(S_TRACE);
  66. foreach (s; step) { mixin(S_TRACE);
  67. if (s is _step) { mixin(S_TRACE);
  68. forceCancel();
  69. return;
  70. }
  71. }
  72. }
  73. void refScenario(Summary summ) { mixin(S_TRACE);
  74. forceCancel();
  75. }
  76. public:
  77. /// Params:
  78. /// prop = ?????
  79. /// shell = ???????
  80. /// dir = ?????????????????
  81. /// step = ???????????????null?
  82. this (Commons comm, Props prop, Shell shell, FlagDir dir, Step step = null) { mixin(S_TRACE);
  83. super(prop, shell, false, prop.msgs.dlgTitStep, prop.images.step, true, prop.var.stepDlg, true);
  84. _comm = comm;
  85. this.prop = prop;
  86. this.dir = dir;
  87. this._step = step;
  88. enterClose = true;
  89. }
  90. /// Returns: ?????????????
  91. @property
  92. Step step() { mixin(S_TRACE);
  93. return _step;
  94. }
  95. /// ?????????????????
  96. @property
  97. string name() { mixin(S_TRACE);
  98. auto name = FlagDir.validName(stepName.getText());
  99. if (_step.parent) { mixin(S_TRACE);
  100. return name;
  101. } else { mixin(S_TRACE);
  102. return dir.createNewStepName(name, _step ? _step.name : "");
  103. }
  104. }
  105. protected:
  106. override void setup(Composite area) { mixin(S_TRACE);
  107. area.setLayout(zeroGridLayout(1));
  108. { mixin(S_TRACE);
  109. auto comp = new Composite(area, SWT.NULL);
  110. comp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  111. comp.setLayout(new GridLayout(5, false));
  112. (new Label(comp, SWT.NULL)).setText(prop.msgs.dlgLblStepName);
  113. stepName = new Text(comp, SWT.BORDER);
  114. mod(stepName);
  115. createTextMenu!Text(_comm, prop, stepName, &catchMod);
  116. setGridMinW(stepName, prop.var.etc.flagNameWidth, GridData.FILL_HORIZONTAL);
  117. checker(stepName);
  118. .listener(stepName, SWT.Modify, &refreshWarning);
  119. auto gd = new GridData(GridData.FILL_VERTICAL);
  120. gd.heightHint = 0;
  121. (new Label(comp, SWT.SEPARATOR | SWT.VERTICAL)).setLayoutData(gd);
  122. (new Label(comp, SWT.NULL)).setText(prop.msgs.dlgLblStepInit);
  123. stepInit = new Combo(comp, SWT.READ_ONLY);
  124. mod(stepInit);
  125. stepInit.setVisibleItemCount(prop.var.etc.comboVisibleItemCount);
  126. setGridMinW(stepInit, prop.var.etc.flagInitWidth);
  127. }
  128. (new Label(area, SWT.SEPARATOR | SWT.HORIZONTAL))
  129. .setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  130. { mixin(S_TRACE);
  131. auto comp = new Composite(area, SWT.NULL);
  132. comp.setLayoutData(new GridData(GridData.FILL_BOTH));
  133. // ???????????????????
  134. Composite valsComp;
  135. int gdc = 0;
  136. for (int i = 0; i < prop.looks.stepMaxCount; i++) { mixin(S_TRACE);
  137. if (i % 5 == 0) { mixin(S_TRACE);
  138. // 1?????5???????????
  139. if (0 < i) { mixin(S_TRACE);
  140. auto gd = new GridData(GridData.FILL_VERTICAL);
  141. gd.heightHint = 0;
  142. (new Label(comp, SWT.SEPARATOR | SWT.VERTICAL)).setLayoutData(gd);
  143. gdc++;
  144. }
  145. valsComp = new Composite(comp, SWT.NULL);
  146. valsComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  147. valsComp.setLayout(new GridLayout(2, false));
  148. gdc++;
  149. }
  150. (new Label(valsComp, SWT.NULL)).setText(.tryFormat(prop.msgs.dlgLblStep, i));
  151. auto t = new Text(valsComp, SWT.BORDER);
  152. createTextMenu!Text(_comm, prop, t, &catchMod);
  153. stepVals ~= t;
  154. mod(t);
  155. stepVals[i].addModifyListener(new ModValue(i));
  156. stepVals[i].addFocusListener(new class FocusAdapter {
  157. override void focusGained(FocusEvent e) { mixin(S_TRACE);
  158. auto text = cast(Text) e.widget;
  159. text.selectAll();
  160. }
  161. });
  162. setGridMinW(stepVals[i], prop.var.etc.flagValueWidth, GridData.FILL_HORIZONTAL);
  163. }
  164. comp.setLayout(new GridLayout(gdc, false));
  165. }
  166. _comm.delFlagAndStep.add(&delStep);
  167. _comm.refScenario.add(&refScenario);
  168. getShell().addDisposeListener(new Dispose);
  169. ignoreMod = true;
  170. scope (exit) ignoreMod = false;
  171. string[] vals;
  172. if (_step !is null) { mixin(S_TRACE);
  173. stepName.setText(_step.name);
  174. foreach (i, stepVal; stepVals) { mixin(S_TRACE);
  175. if (i < _step.count) { mixin(S_TRACE);
  176. stepVal.setText(_step.getValue(i));
  177. } else { mixin(S_TRACE);
  178. stepVal.setText(.tryFormat(prop.msgs.dlgTxtStep, i));
  179. }
  180. vals ~= stepVal.getText();
  181. }
  182. } else { mixin(S_TRACE);
  183. stepName.setText("");
  184. foreach (i, stepVal; stepVals) { mixin(S_TRACE);
  185. stepVal.setText(.tryFormat(prop.msgs.dlgTxtStep, i));
  186. vals ~= stepVal.getText();
  187. }
  188. }
  189. if (!_step.parent) { mixin(S_TRACE);
  190. // ?????
  191. stepName.setText("");
  192. }
  193. stepName.selectAll();
  194. setComboItems(stepInit, vals);
  195. stepInit.select(_step is null ? 0 : _step.select);
  196. }
  197. override bool apply() { mixin(S_TRACE);
  198. string[] vals;
  199. foreach (stepVal; stepVals) { mixin(S_TRACE);
  200. vals ~= stepVal.getText();
  201. }
  202. if (_step.parent) { mixin(S_TRACE);
  203. _step.name = this.name;
  204. _step.setValues(vals, stepInit.getSelectionIndex());
  205. } else { mixin(S_TRACE);
  206. _step = new Step(this.name, vals, stepInit.getSelectionIndex());
  207. dir.add(_step);
  208. }
  209. _comm.refFlagAndStep.call([], [_step]);
  210. return true;
  211. }
  212. }
  213. /// ?????????????
  214. public class FlagEditDialog : AbsDialog {
  215. private:
  216. Commons _comm;
  217. Props prop;
  218. Flag _flag;
  219. FlagDir dir;
  220. Text flagName;
  221. Combo flagInit;
  222. Combo flagTrue;
  223. Combo flagFalse;
  224. void refreshWarning() { mixin(S_TRACE);
  225. string[] ws;
  226. if (prop.sys.isSystemVar(flagName.getText())) { mixin(S_TRACE);
  227. ws ~= .tryFormat(prop.msgs.warningSystemVarName, prop.sys.prefixSystemVarName);
  228. }
  229. warning = ws;
  230. }
  231. class ModOnOff : SelectionAdapter, ModifyListener {
  232. private:
  233. int index;
  234. void change(E)(E e) { mixin(S_TRACE);
  235. if (index < flagInit.getItemCount()) { mixin(S_TRACE);
  236. flagInit.setItem(index, (cast(Combo) e.getSource()).getText());
  237. }
  238. }
  239. public:
  240. this(int index) { mixin(S_TRACE);
  241. this.index = index;
  242. }
  243. override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  244. change(e);
  245. }
  246. override void modifyText(ModifyEvent e) { mixin(S_TRACE);
  247. change(e);
  248. }
  249. }
  250. class Dispose : DisposeListener {
  251. override void widgetDisposed(DisposeEvent e) { mixin(S_TRACE);
  252. _comm.delFlagAndStep.remove(&delFlag);
  253. _comm.refScenario.remove(&refScenario);
  254. }
  255. }
  256. void delFlag(Flag[] flag, Step[] step) { mixin(S_TRACE);
  257. foreach (f; flag) { mixin(S_TRACE);
  258. if (f is _flag) { mixin(S_TRACE);
  259. forceCancel();
  260. return;
  261. }
  262. }
  263. }
  264. void refScenario(Summary summ) { mixin(S_TRACE);
  265. forceCancel();
  266. }
  267. public:
  268. /// Params:
  269. /// prop = ?????
  270. /// shell = ???????
  271. /// dir = ????????????????
  272. /// flag = ??????????????null?
  273. this(Commons comm, Props prop, Shell shell, FlagDir dir, Flag flag = null) { mixin(S_TRACE);
  274. super(prop, shell, false, prop.msgs.dlgTitFlag, prop.images.flag, true, prop.var.flagDlg, true);
  275. _comm = comm;
  276. this.prop = prop;
  277. this._flag = flag;
  278. this.dir = dir;
  279. enterClose = true;
  280. }
  281. /// Returns: ????????????
  282. @property
  283. Flag flag() { mixin(S_TRACE);
  284. return _flag;
  285. }
  286. /// ?????????????????
  287. @property
  288. string name() { mixin(S_TRACE);
  289. auto name = FlagDir.validName(flagName.getText());
  290. if (_flag.parent) { mixin(S_TRACE);
  291. return name;
  292. } else { mixin(S_TRACE);
  293. return dir.createNewFlagName(name, _flag ? _flag.name : "");
  294. }
  295. }
  296. protected:
  297. private static void setMinW(Control c, int minW, int gridStyle = SWT.NULL) { mixin(S_TRACE);
  298. auto gd = new GridData(gridStyle);
  299. int w = c.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
  300. gd.widthHint = w > minW ? w : minW;
  301. c.setLayoutData(gd);
  302. }
  303. override void setup(Composite area) { mixin(S_TRACE);
  304. area.setLayout(zeroGridLayout(1));
  305. { mixin(S_TRACE);
  306. auto comp = new Composite(area, SWT.NULL);
  307. comp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  308. comp.setLayout(new GridLayout(5, false));
  309. (new Label(comp, SWT.NULL)).setText(prop.msgs.dlgLblFlagName);
  310. flagName = new Text(comp, SWT.BORDER);
  311. createTextMenu!Text(_comm, prop, flagName, &catchMod);
  312. mod(flagName);
  313. setGridMinW(flagName, prop.var.etc.flagNameWidth, GridData.FILL_HORIZONTAL);
  314. checker(flagName);
  315. .listener(flagName, SWT.Modify, &refreshWarning);
  316. auto gd = new GridData(GridData.FILL_VERTICAL);
  317. gd.heightHint = 0;
  318. (new Label(comp, SWT.SEPARATOR | SWT.VERTICAL)).setLayoutData(gd);
  319. (new Label(comp, SWT.NULL)).setText(prop.msgs.dlgLblFlagInit);
  320. flagInit = new Combo(comp, SWT.READ_ONLY);
  321. mod(flagInit);
  322. setGridMinW(flagInit, prop.var.etc.flagInitWidth);
  323. }
  324. (new Label(area, SWT.SEPARATOR | SWT.HORIZONTAL))
  325. .setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  326. { mixin(S_TRACE);
  327. auto ocomp = new Composite(area, SWT.NONE);
  328. ocomp.setLayoutData(new GridData(GridData.FILL_BOTH));
  329. auto cl = new CenterLayout(SWT.HORIZONTAL | SWT.VERTICAL, 0);
  330. cl.fillHorizontal = true;
  331. ocomp.setLayout(cl);
  332. auto comp = new Composite(ocomp, SWT.NONE);
  333. comp.setLayout(new GridLayout(2, false));
  334. (new Label(comp, SWT.NULL)).setText(prop.msgs.dlgLblFlagTrue);
  335. flagTrue = new Combo(comp, SWT.NULL);
  336. mod(flagTrue);
  337. setComboItems(flagTrue, prop.var.etc.flagTrues.dup);
  338. flagTrue.setVisibleItemCount(prop.var.etc.comboVisibleItemCount);
  339. createTextMenu!Combo(_comm, prop, flagTrue, &catchMod);
  340. auto tmod = new ModOnOff(0);
  341. flagTrue.addModifyListener(tmod);
  342. flagTrue.addSelectionListener(tmod);
  343. setGridMinW(flagTrue, prop.var.etc.flagValueWidth, GridData.FILL_HORIZONTAL);
  344. (new Label(comp, SWT.NULL)).setText(prop.msgs.dlgLblFlagFalse);
  345. flagFalse = new Combo(comp, SWT.NULL);
  346. mod(flagFalse);
  347. setComboItems(flagFalse, prop.var.etc.flagFalses.dup);
  348. flagFalse.setVisibleItemCount(prop.var.etc.comboVisibleItemCount);
  349. createTextMenu!Combo(_comm, prop, flagFalse, &catchMod);
  350. auto fmod = new ModOnOff(1);
  351. flagFalse.addModifyListener(fmod);
  352. flagFalse.addSelectionListener(fmod);
  353. setGridMinW(flagFalse, prop.var.etc.flagValueWidth, GridData.FILL_HORIZONTAL);
  354. }
  355. _comm.delFlagAndStep.add(&delFlag);
  356. _comm.refScenario.add(&refScenario);
  357. getShell().addDisposeListener(new Dispose);
  358. ignoreMod = true;
  359. scope (exit) ignoreMod = false;
  360. if (_flag !is null) { mixin(S_TRACE);
  361. flagName.setText(_flag.name);
  362. flagTrue.setText(_flag.on);
  363. if (-1 == flagTrue.indexOf(_flag.on)) flagTrue.add(_flag.on, 0);
  364. flagFalse.setText(_flag.off);
  365. if (-1 == flagFalse.indexOf(_flag.off)) flagFalse.add(_flag.off, 0);
  366. setComboItems(flagInit, [flagTrue.getText(), flagFalse.getText()]);
  367. flagInit.select(_flag.onOff ? 0 : 1);
  368. } else { mixin(S_TRACE);
  369. flagName.setText("");
  370. flagTrue.setText(prop.var.etc.flagTrues.length > 0 ? prop.var.etc.flagTrues[0] : "");
  371. flagFalse.setText(prop.var.etc.flagFalses.length > 0 ? prop.var.etc.flagFalses[0] : "");
  372. setComboItems(flagInit, [flagTrue.getText(), flagFalse.getText()]);
  373. flagInit.select(0);
  374. }
  375. if (!_flag.parent) { mixin(S_TRACE);
  376. // ?????
  377. flagName.setText("");
  378. }
  379. flagName.selectAll();
  380. }
  381. override bool apply() { mixin(S_TRACE);
  382. if (_flag.parent) { mixin(S_TRACE);
  383. _flag.name = this.name;
  384. _flag.onOff = flagInit.getSelectionIndex() == 0;
  385. _flag.on = flagTrue.getText();
  386. _flag.off = flagFalse.getText();
  387. } else { mixin(S_TRACE);
  388. _flag = new Flag(this.name, flagTrue.getText(), flagFalse.getText(),
  389. flagInit.getSelectionIndex() == 0);
  390. dir.add(_flag);
  391. }
  392. _comm.refFlagAndStep.call([_flag], []);
  393. return true;
  394. }
  395. }
  396. private abstract class FTVUndo : Undo {
  397. protected FlagTable _v;
  398. protected Commons comm;
  399. protected string _dir;
  400. private string _selectedDir;
  401. private string[] _selectedF;
  402. private string[] _selectedS;
  403. private string[] _selectedFB;
  404. private string[] _selectedSB;
  405. protected FlagDir selDir = null;
  406. this (FlagTable v, Commons comm, FlagDir dir) { mixin(S_TRACE);
  407. _v = v;
  408. _dir = dir.path;
  409. this.comm = comm;
  410. saveSelected(v);
  411. }
  412. @property
  413. protected FlagDir dir() { mixin(S_TRACE);
  414. return cast(FlagDir) comm.summary.flagDirRoot.findPath(_dir, false);
  415. }
  416. private void saveSelected(FlagTable v) { mixin(S_TRACE);
  417. auto dir = this.dir();
  418. if (!dir) return;
  419. _selectedDir = dir.cwxPath(true);
  420. if (v && v.flags && !v.flags.isDisposed()) { mixin(S_TRACE);
  421. _selectedF = v.selectionFlagNames;
  422. _selectedS = v.selectionStepNames;
  423. } else { mixin(S_TRACE);
  424. _selectedF.length = 0;
  425. _selectedS.length = 0;
  426. }
  427. }
  428. void udb(FlagTable v) { mixin(S_TRACE);
  429. _selectedFB = _selectedF.dup;
  430. _selectedSB = _selectedS.dup;
  431. saveSelected(v);
  432. if (v && v.flags && !v.flags.isDisposed()) { mixin(S_TRACE);
  433. .forceFocus(v.flags, false);
  434. }
  435. }
  436. void uda(FlagTable v) { mixin(S_TRACE);
  437. if (v && v.flags && !v.flags.isDisposed()) { mixin(S_TRACE);
  438. if (selDir) { mixin(S_TRACE);
  439. if (comm.openCWXPath(selDir.cwxPath(true), true)) { mixin(S_TRACE);
  440. v.flags.deselectAll();
  441. }
  442. } else { mixin(S_TRACE);
  443. if (comm.openCWXPath(_selectedDir, true)) { mixin(S_TRACE);
  444. v.flags.deselectAll();
  445. v.selectFlagNames(_selectedFB);
  446. v.selectStepNames(_selectedSB);
  447. }
  448. }
  449. v.refreshStatusLine();
  450. }
  451. selDir = null;
  452. comm.refreshToolBar();
  453. }
  454. FlagTable view() { mixin(S_TRACE);
  455. return _v;
  456. }
  457. abstract override void undo();
  458. abstract override void redo();
  459. abstract override void dispose();
  460. }
  461. package class UndoAllVariables : FTVUndo {
  462. private FlagDir _root;
  463. private FlagDir _copyRoot;
  464. this (FlagTable v, Commons comm, FlagDir dir, FlagDir root) { mixin(S_TRACE);
  465. super (v, comm, dir);
  466. _root = root;
  467. _copyRoot = new FlagDir(root);
  468. }
  469. private void impl() { mixin(S_TRACE);
  470. auto v = view();
  471. udb(v);
  472. scope (exit) uda(v);
  473. auto copy = _copyRoot;
  474. _copyRoot = new FlagDir(_root);
  475. _root.removeAll();
  476. foreach (f; copy.flags) _root.add(f);
  477. foreach (f; copy.steps) _root.add(f);
  478. foreach (f; copy.subDirs) _root.add(f);
  479. comm.refFlagAndStep.call(_root.allFlags, _root.allSteps);
  480. comm.openFlagWin(false).dirs.refresh();
  481. }
  482. override void undo() {impl();}
  483. override void redo() {impl();}
  484. override void dispose() {}
  485. }
  486. package class UndoEditN {
  487. private CWXPath _f;
  488. private string _name;
  489. this (FlagDir dir, int index, string oldName, int value) { mixin(S_TRACE);
  490. auto p = FlagTable.fromIndex(dir, index);
  491. auto f = cast(Flag)p;
  492. if (f) { mixin(S_TRACE);
  493. auto flag = new Flag(f);
  494. _name = flag.name;
  495. flag.name = oldName;
  496. if (-1 != value) flag.onOff = value == 0;
  497. _f = flag;
  498. }
  499. auto s = cast(Step)p;
  500. if (s) { mixin(S_TRACE);
  501. auto step = new Step(s);
  502. _name = step.name;
  503. step.name = oldName;
  504. if (-1 != value) step.select = value;
  505. _f = step;
  506. }
  507. }
  508. CWXPath impl(Commons comm, FlagDir dir, out string newName) { mixin(S_TRACE);
  509. assert (dir);
  510. auto fB = _f;
  511. if (cast(Flag)fB) { mixin(S_TRACE);
  512. auto f = dir.getFlag(_name);
  513. _f = new Flag(f);
  514. auto o = cast(Flag)fB;
  515. assert (o);
  516. _name = o.name;
  517. bool refVal = o.on != f.on || o.off != f.off;
  518. newName = o.name;
  519. o.name = f.name;
  520. f.copyFrom(o);
  521. refVal |= newName != f.name;
  522. if (refVal) { mixin(S_TRACE);
  523. return f;
  524. }
  525. } else { mixin(S_TRACE);
  526. assert (cast(Step)fB);
  527. auto s = dir.getStep(_name);
  528. _f = new Step(s);
  529. auto o = cast(Step)fB;
  530. assert (o);
  531. _name = o.name;
  532. bool refVal = o.values != s.values;
  533. newName = o.name;
  534. o.name = s.name;
  535. s.copyFrom(o);
  536. refVal |= newName != s.name;
  537. if (refVal) { mixin(S_TRACE);
  538. return s;
  539. }
  540. }
  541. return null;
  542. }
  543. }
  544. package class UndoEdit : FTVUndo {
  545. private UndoEditN[] _impl;
  546. this (FlagTable v, Commons comm, FlagDir dir, int[] index, string[] oldName, int[] oldValues) in { mixin(S_TRACE);
  547. assert (index.length == oldName.length);
  548. assert (!oldValues.length || oldValues.length == index.length);
  549. } body { mixin(S_TRACE);
  550. super (v, comm, dir);
  551. foreach (i, idx; index) { mixin(S_TRACE);
  552. _impl ~= new UndoEditN(dir, idx, oldName[i], oldValues.length ? oldValues[i] : -1);
  553. }
  554. }
  555. private void impl() { mixin(S_TRACE);
  556. auto v = view();
  557. udb(v);
  558. scope (exit) uda(v);
  559. auto dir = this.dir();
  560. Flag[] refF;
  561. Step[] refS;
  562. string[] newNameF;
  563. string[] newNameS;
  564. foreach (impl; _impl) { mixin(S_TRACE);
  565. string newName;
  566. auto refVal = impl.impl(comm, dir, newName);
  567. if (cast(Flag)refVal) { mixin(S_TRACE);
  568. refF ~= cast(Flag)refVal;
  569. newNameF ~= newName;
  570. } else if (cast(Step)refVal) { mixin(S_TRACE);
  571. refS ~= cast(Step)refVal;
  572. newNameS ~= newName;
  573. }
  574. }
  575. FlagTable.setNames(refF, newNameF, comm.summary.useCounter);
  576. FlagTable.setNames(refS, newNameS, comm.summary.useCounter);
  577. comm.refFlagAndStep.call(refF, refS);
  578. if (v && v.flags && !v.flags.isDisposed()) { mixin(S_TRACE);
  579. v.refresh();
  580. }
  581. }
  582. override void undo() {impl();}
  583. override void redo() {impl();}
  584. override void dispose() {}
  585. }
  586. package class UndoInsertDelete : FTVUndo {
  587. private bool _insert;
  588. /// insert
  589. private int[] _dirIndices;
  590. private string[] _flagName;
  591. private string[] _stepName;
  592. /// delete
  593. private FlagDir[int] _ds;
  594. private Flag[] _fs;
  595. private Step[] _ss;
  596. /// ????????
  597. this (FlagTable v, Commons comm, FlagDir dir, string[] selectedF, string[] selectedS, int[] dirIndices, string[] flagName, string[] stepName) { mixin(S_TRACE);
  598. super (v, comm, dir);
  599. _selectedF = selectedF.dup;
  600. _selectedS = selectedS.dup;
  601. _dirIndices = dirIndices.dup;
  602. _flagName = flagName.dup;
  603. _stepName = stepName.dup;
  604. _insert = true;
  605. }
  606. /// ????????
  607. this (FlagTable v, Commons comm, FlagDir dir, string[] selectedF, string[] selectedS, FlagDir[int] ds, Flag[] fs, Step[] ss) { mixin(S_TRACE);
  608. super (v, comm, dir);
  609. _selectedF = selectedF.dup;
  610. _selectedS = selectedS.dup;
  611. save(ds, fs, ss);
  612. _insert = false;
  613. }
  614. private void save(FlagDir[int] ds, Flag[] fs, Step[] ss) { mixin(S_TRACE);
  615. _ds = ds;
  616. foreach (index, d; _ds) { mixin(S_TRACE);
  617. _ds[index] = new FlagDir(d);
  618. }
  619. _fs.length = 0;
  620. foreach (f; fs) { mixin(S_TRACE);
  621. _fs ~= new Flag(f);
  622. }
  623. _ss.length = 0;
  624. foreach (s; ss) { mixin(S_TRACE);
  625. _ss ~= new Step(s);
  626. }
  627. }
  628. private void undoInsert(FlagTable v) { mixin(S_TRACE);
  629. _insert = false;
  630. FlagDir[int] ds;
  631. Flag[] fs;
  632. Step[] ss;
  633. auto dir = this.dir();
  634. foreach (i; _dirIndices) { mixin(S_TRACE);
  635. auto d = dir.subDirs[i];
  636. if (d) ds[i] = d;
  637. }
  638. foreach (n; _flagName) { mixin(S_TRACE);
  639. auto f = dir.getFlag(n);
  640. if (f) fs ~= f;
  641. }
  642. foreach (n; _stepName) { mixin(S_TRACE);
  643. auto s = dir.getStep(n);
  644. if (s) ss ~= s;
  645. }
  646. save(ds, fs, ss);
  647. foreach (f; fs) { mixin(S_TRACE);
  648. dir.remove(f);
  649. }
  650. foreach (s; ss) { mixin(S_TRACE);
  651. dir.remove(s);
  652. }
  653. foreach (d; ds) { mixin(S_TRACE);
  654. dir.remove(d);
  655. fs ~= d.allFlags;
  656. ss ~= d.allSteps;
  657. }
  658. if (v && v.flags && !v.flags.isDisposed()) { mixin(S_TRACE);
  659. v.refresh();
  660. }
  661. if (ds.length) comm.delFlagDir.call(ds.values);
  662. if (fs.length || ss.length) comm.delFlagAndStep.call(fs, ss);
  663. }
  664. private void undoDelete(FlagTable v) { mixin(S_TRACE);
  665. _insert = true;
  666. auto dir = this.dir();
  667. _dirIndices.length = 0;
  668. _flagName.length = 0;
  669. _stepName.length = 0;
  670. selDir = (_ds.length == 1 && !_fs.length && !_ss.length) ? _ds.values[0] : null;
  671. foreach (f; _fs) { mixin(S_TRACE);
  672. _flagName ~= f.name;
  673. dir.add(f);
  674. }
  675. foreach (s; _ss) { mixin(S_TRACE);
  676. _stepName ~= s.name;
  677. dir.add(s);
  678. }
  679. foreach (index; _ds.keys.sort) { mixin(S_TRACE);
  680. auto d = _ds[index];
  681. _dirIndices ~= index;
  682. dir.insert(index, d);
  683. _fs ~= d.allFlags;
  684. _ss ~= d.allSteps;
  685. }
  686. if (v && v.flags && !v.flags.isDisposed()) { mixin(S_TRACE);
  687. v.refresh();
  688. }
  689. if (_ds.length) comm.refFlagDir.call(_ds.values);
  690. if (_fs.length || _ss.length) comm.refFlagAndStep.call(_fs, _ss);
  691. }
  692. override void undo() { mixin(S_TRACE);
  693. auto v = view();
  694. udb(v);
  695. scope (exit) uda(v);
  696. undoImpl(v);
  697. }
  698. private void undoImpl(FlagTable v) { mixin(S_TRACE);
  699. if (_insert) { mixin(S_TRACE);
  700. undoInsert(v);
  701. } else { mixin(S_TRACE);
  702. undoDelete(v);
  703. }
  704. }
  705. override void redo() { mixin(S_TRACE);
  706. auto v = view();
  707. udb(v);
  708. scope (exit) uda(v);
  709. redoImpl(v);
  710. }
  711. private void redoImpl(FlagTable v) { mixin(S_TRACE);
  712. undoImpl(v);
  713. }
  714. override void dispose() {}
  715. }
  716. package class UndoMove : FTVUndo {
  717. private UndoInsertDelete _dir1;
  718. private UndoInsertDelete _dir2;
  719. private string[string] _cFlags;
  720. private string[string] _cSteps;
  721. this (FlagTable v, Commons comm, string[] selectedF, string[] selectedS, FlagDir to, int[] dirIndices, string[] flagName, string[] stepName, FlagDir from, FlagDir[int] ds, Flag[] fs, Step[] ss, Flag[string] cFlags, Step[string] cSteps) { mixin(S_TRACE);
  722. super (v, comm, from);
  723. _selectedF = selectedF.dup;
  724. _selectedS = selectedS.dup;
  725. assert (dirIndices.length == ds.length);
  726. assert (flagName.length == fs.length);
  727. assert (stepName.length == ss.length);
  728. _dir1 = new UndoInsertDelete(v, comm, to, selectedF, selectedS, dirIndices, flagName, stepName);
  729. _dir2 = new UndoInsertDelete(v, comm, from, selectedF, selectedS, ds, fs, ss);
  730. foreach (oPath, flag; cFlags) { mixin(S_TRACE);
  731. _cFlags[oPath] = flag.path;
  732. }
  733. foreach (oPath, step; cSteps) { mixin(S_TRACE);
  734. _cSteps[oPath] = step.path;
  735. }
  736. }
  737. private void change(FlagTable v) { mixin(S_TRACE);
  738. string[string] cFlags;
  739. string[string] cSteps;
  740. foreach (nPath, oPath; _cFlags) { mixin(S_TRACE);
  741. cFlags[oPath] = nPath;
  742. comm.summary.useCounter.change(toFlagId(oPath), toFlagId(nPath));
  743. }
  744. foreach (nPath, oPath; _cSteps) { mixin(S_TRACE);
  745. cSteps[oPath] = nPath;
  746. comm.summary.useCounter.change(toStepId(oPath), toStepId(nPath));
  747. }
  748. _cFlags = cFlags;
  749. _cSteps = cSteps;
  750. if (v && v.flags && !v.flags.isDisposed()) { mixin(S_TRACE);
  751. v.__refreshUseCount();
  752. }
  753. }
  754. override void undo() { mixin(S_TRACE);
  755. auto v = view();
  756. udb(v);
  757. scope (exit) uda(v);
  758. _dir1.undoImpl(v);
  759. _dir2.undoImpl(v);
  760. change(v);
  761. }
  762. override void redo() { mixin(S_TRACE);
  763. auto v = view();
  764. udb(v);
  765. scope (exit) uda(v);
  766. _dir2.redoImpl(v);
  767. _dir1.redoImpl(v);
  768. change(v);
  769. }
  770. override void dispose() { mixin(S_TRACE);
  771. _dir1.dispose();
  772. _dir2.dispose();
  773. }
  774. }
  775. package class UndoEditDir : FTVUndo {
  776. private string _oldName;
  777. this (FlagTable v, Commons comm, FlagDir dir, string oldName) { mixin(S_TRACE);
  778. super (v, comm, dir);
  779. _oldName = oldName;
  780. }
  781. private void impl() { mixin(S_TRACE);
  782. auto v = view();
  783. udb(v);
  784. scope (exit) uda(v);
  785. auto dir = this.dir();
  786. string oldName = dir.name;
  787. dir.rename(_oldName, comm.summary.useCounter);
  788. if (dir.parent) dir.parent.sortSubDirs(false);
  789. _oldName = oldName;
  790. comm.refFlagDir.call([dir]);
  791. _dir = dir.path;
  792. }
  793. override void undo() {impl();}
  794. override void redo() {impl();}
  795. override void dispose() {}
  796. }
  797. package class UndoSwap : FTVUndo {
  798. private FlagDir _parent;
  799. private int _index1, _index2;
  800. this (FlagTable v, Commons comm, FlagDir dir, FlagDir parent, int index1, int index2) { mixin(S_TRACE);
  801. super (v, comm, dir);
  802. _parent = parent;
  803. _index1 = index1;
  804. _index2 = index2;
  805. }
  806. private void impl() { mixin(S_TRACE);
  807. auto v = view();
  808. udb(v);
  809. scope (exit) uda(v);
  810. _parent.swapDir(_index1, _index2);
  811. comm.refFlagDir.call([_parent, _parent.subDirs[_index1], _parent.subDirs[_index2]]);
  812. }
  813. override void undo() {impl();}
  814. override void redo() {impl();}
  815. override void dispose() {}
  816. }
  817. public class FlagTable : TCPD {
  818. private:
  819. void storeEdit(int[] index, string[] oldName, int[] oldValues = []) { mixin(S_TRACE);
  820. _undo ~= new UndoEdit(this, _comm, _dir, index, oldName, oldValues);
  821. }
  822. void storeEdit(int index, string oldName, int oldValue) { mixin(S_TRACE);
  823. _undo ~= new UndoEdit(this, _comm, _dir, [index], [oldName], [oldValue]);
  824. }
  825. void storeInsert(string[] selectedF, string[] selectedS, string[] flagName, string[] stepName) { mixin(S_TRACE);
  826. _undo ~= new UndoInsertDelete(this, _comm, _dir, selectedF, selectedS, [], flagName, stepName);
  827. }
  828. void storeDelete(string[] selectedF, string[] selectedS, Flag[] fs, Step[] ss) { mixin(S_TRACE);
  829. FlagDir[int] ds;
  830. _undo ~= new UndoInsertDelete(this, _comm, _dir, selectedF, selectedS, ds, fs, ss);
  831. }
  832. static int indexOf(FlagDir dir, CWXPath p) { mixin(S_TRACE);
  833. int i = 0;
  834. foreach (s; dir.steps) { mixin(S_TRACE);
  835. if (s is p) { mixin(S_TRACE);
  836. return i;
  837. }
  838. i++;
  839. }
  840. foreach (f; dir.flags) { mixin(S_TRACE);
  841. if (f is p) { mixin(S_TRACE);
  842. return i;
  843. }
  844. i++;
  845. }
  846. return -1;
  847. }
  848. static CWXPath fromIndex(FlagDir dir, int index) { mixin(S_TRACE);
  849. if (dir.steps.length <= index) { mixin(S_TRACE);
  850. return dir.flags[index - dir.steps.length];
  851. }
  852. return dir.steps[index];
  853. }
  854. static int toFlagIndex(FlagDir dir, int index) { mixin(S_TRACE);
  855. return index - dir.steps.length;
  856. }
  857. static int toStepIndex(FlagDir dir, int index) { mixin(S_TRACE);
  858. return index;
  859. }
  860. static const NAME = 0;
  861. static const VALUE = 1;
  862. static const UC = 2;
  863. void refreshFlags() { mixin(S_TRACE);
  864. if (_dir) { mixin(S_TRACE);
  865. int i = 0;
  866. foreach (f; _dir.steps) { mixin(S_TRACE);
  867. if (!_incSearch.match(f.name, f)) continue;
  868. TableItem itm;
  869. if (i < flags.getItemCount()) { mixin(S_TRACE);
  870. itm = flags.getItem(i);
  871. } else { mixin(S_TRACE);
  872. itm = new TableItem(flags, SWT.NONE);
  873. }
  874. itm.setImage(0, prop.images.step);
  875. itm.setText(NAME, f.name);
  876. itm.setText(VALUE, f.value);
  877. itm.setText(UC, to!(string)(uc.get(toStepId(f.path))));
  878. itm.setData(f);
  879. i++;
  880. }
  881. foreach (f; _dir.flags) { mixin(S_TRACE);
  882. if (!_incSearch.match(f.name, f)) continue;
  883. TableItem itm;
  884. if (i < flags.getItemCount()) { mixin(S_TRACE);
  885. itm = flags.getItem(i);
  886. } else { mixin(S_TRACE);
  887. itm = new TableItem(flags, SWT.NONE);
  888. }
  889. itm.setImage(0, prop.images.flag);
  890. itm.setText(NAME, f.name);
  891. itm.setText(VALUE, f.onOff ? f.on : f.off);
  892. itm.setText(UC, to!(string)(uc.get(toFlagId(f.path))));
  893. itm.setData(f);
  894. i++;
  895. }
  896. if (i < flags.getItemCount()) { mixin(S_TRACE);
  897. flags.remove(i, flags.getItemCount() - 1);
  898. }
  899. } else { mixin(S_TRACE);
  900. flags.removeAll();
  901. }
  902. }
  903. Props prop;
  904. Commons _comm;
  905. UseCounter uc;
  906. Table flags;
  907. FlagDir _dir = null;
  908. string _statusLine = "";
  909. FlagEditDialog[Flag] _editDlgsF;
  910. StepEditDialog[Step] _editDlgsS;
  911. IncSearch _incSearch = null;
  912. private void incSearch() { mixin(S_TRACE);
  913. .forceFocus(flags, true);
  914. _incSearch.startIncSearch();
  915. }
  916. UndoManager _undo;
  917. void editFlag(FlagDir parent, Flag flag) { mixin(S_TRACE);
  918. bool createMode = flag is null;
  919. string old = createMode ? null : flag.path;
  920. if (!flag) { mixin(S_TRACE);
  921. string on = prop.var.etc.flagTrues.length > 0 ? prop.var.etc.flagTrues[0] : "";
  922. string off = prop.var.etc.flagFalses.length > 0 ? prop.var.etc.flagFalses[0] : "";
  923. flag = new Flag("", on, off, true);
  924. }
  925. auto p = flag in _editDlgsF;
  926. if (p) { mixin(S_TRACE);
  927. p.active();
  928. return;
  929. }
  930. auto dlg = new FlagEditDialog(_comm, prop, dlgParShl, parent, flag);
  931. string oldName = "";
  932. int oldValue = 0;
  933. dlg.applyEvent ~= { mixin(S_TRACE);
  934. int i = indexOf(parent, flag);
  935. if (-1 != i) { mixin(S_TRACE);
  936. assert (!createMode);
  937. oldName = flag.name;
  938. oldValue = flag.onOff ? 0 : 1;
  939. }
  940. };
  941. dlg.appliedEvent ~= { mixin(S_TRACE);
  942. auto flag = dlg.flag;
  943. if (old && old != flag.path) uc.change(toFlagId(old), toFlagId(flag.path), true);
  944. if (createMode) { mixin(S_TRACE);
  945. string[] selsF;
  946. string[] selsS;
  947. if (flags && !flags.isDisposed()) { mixin(S_TRACE);
  948. selsF = selectionFlagNames;
  949. selsS = selectionStepNames;
  950. }
  951. storeInsert(selsF, selsS, [flag.name], []);
  952. createMode = false;
  953. } else { mixin(S_TRACE);
  954. storeEdit(indexOf(parent, flag), oldName, oldValue);
  955. }
  956. _comm.openCWXPath(flag.cwxPath(true), false);
  957. refresh(flag);
  958. _comm.refFlagAndStep.call([flag], []);
  959. _comm.refreshToolBar();
  960. };
  961. _editDlgsF[flag] = dlg;
  962. dlg.closeEvent ~= { mixin(S_TRACE);
  963. _editDlgsF.remove(flag);
  964. };
  965. dlg.open();
  966. }
  967. void editStep(FlagDir parent, Step step) { mixin(S_TRACE);
  968. bool createMode = step is null;
  969. string old = createMode ? null : step.path;
  970. if (!step) { mixin(S_TRACE);
  971. string[] vals;
  972. foreach (i; 0 .. prop.looks.stepMaxCount) { mixin(S_TRACE);
  973. vals ~= .tryFormat(prop.msgs.dlgTxtStep, i);
  974. }
  975. step = new Step("", vals, 0);
  976. }
  977. auto p = step in _editDlgsS;
  978. if (p) { mixin(S_TRACE);
  979. p.active();
  980. return;
  981. }
  982. auto dlg = new StepEditDialog(_comm, prop, dlgParShl, parent, step);
  983. string oldName = "";
  984. int oldValue = 0;
  985. dlg.applyEvent ~= { mixin(S_TRACE);
  986. int i = indexOf(parent, step);
  987. if (-1 != i) { mixin(S_TRACE);
  988. assert (!createMode);
  989. oldName = step.name;
  990. oldValue = step.select;
  991. }
  992. };
  993. dlg.appliedEvent ~= { mixin(S_TRACE);
  994. auto step = dlg.step;
  995. if (old && old != step.path) uc.change(toStepId(old), toStepId(step.path), true);
  996. if (createMode) { mixin(S_TRACE);
  997. string[] selsF;
  998. string[] selsS;
  999. if (flags && !flags.isDisposed()) { mixin(S_TRACE);
  1000. selsF = selectionFlagNames;
  1001. selsS = selectionStepNames;
  1002. }
  1003. storeInsert(selsF, selsS, [step.name], []);
  1004. createMode = false;
  1005. } else { mixin(S_TRACE);
  1006. storeEdit(indexOf(parent, step), oldName, oldValue);
  1007. }
  1008. _comm.openCWXPath(step.cwxPath(true), false);
  1009. refresh(step);
  1010. _comm.refFlagAndStep.call([], [step]);
  1011. _comm.refreshToolBar();
  1012. };
  1013. _editDlgsS[step] = dlg;
  1014. dlg.closeEvent ~= { mixin(S_TRACE);
  1015. _editDlgsS.remove(step);
  1016. };
  1017. dlg.open();
  1018. }
  1019. class MListener : MouseAdapter {
  1020. public:
  1021. override void mouseDoubleClick(MouseEvent e) { mixin(S_TRACE);
  1022. if (e.button == 1) { mixin(S_TRACE);
  1023. edit();
  1024. }
  1025. }
  1026. }
  1027. class KListener : KeyAdapter {
  1028. public:
  1029. override void keyPressed(KeyEvent e) { mixin(S_TRACE);
  1030. if (e.character == SWT.CR) { mixin(S_TRACE);
  1031. edit();
  1032. }
  1033. }
  1034. }
  1035. /// ??????????????????
  1036. /// Params:
  1037. /// fs = ?????????????????
  1038. /// ss = ??????????????????
  1039. /// Returns: ?????true?
  1040. bool getSelectionFlagAndStep(out Flag[] fs, out Step[] ss) { mixin(S_TRACE);
  1041. auto indices = flags.getSelectionIndices();
  1042. if (indices.length > 0) { mixin(S_TRACE);
  1043. foreach (i; indices) { mixin(S_TRACE);
  1044. auto itm = flags.getItem(i);
  1045. if (auto s = cast(Step)itm.getData()) { mixin(S_TRACE);
  1046. ss ~= s;
  1047. } else if (auto f = cast(Flag)itm.getData()) { mixin(S_TRACE);
  1048. fs ~= f;
  1049. } else assert (0);
  1050. }
  1051. return true;
  1052. } else { mixin(S_TRACE);
  1053. return false;
  1054. }
  1055. }
  1056. void selectNamesImpl(F)(string[] names) { mixin(S_TRACE);
  1057. auto set = new HashSet!string;
  1058. foreach (name; names) set.add(name.toLower());
  1059. foreach (i, itm; flags.getItems()) { mixin(S_TRACE);
  1060. if (auto f = cast(F)itm.getData()) { mixin(S_TRACE);
  1061. if (set.contains(f.name.toLower())) { mixin(S_TRACE);
  1062. flags.select(i);
  1063. }
  1064. }
  1065. }
  1066. }
  1067. void selectFlagNames(string[] names) { mixin(S_TRACE);
  1068. selectNamesImpl!Flag(names);
  1069. }
  1070. void selectStepNames(string[] names) { mixin(S_TRACE);
  1071. selectNamesImpl!Step(names);
  1072. }
  1073. Flag[] _dragFlags;
  1074. Step[] _dragSteps;
  1075. class FlagDragListener : DragSourceListener {
  1076. private:
  1077. int[] dragIndices;
  1078. public:
  1079. override void dragStart(DragSourceEvent e) { mixin(S_TRACE);
  1080. e.doit = flags.getSelectionCount() > 0;
  1081. }
  1082. override void dragSetData(DragSourceEvent e) { mixin(S_TRACE);
  1083. if (XMLBytesTransfer.getInstance().isSupportedType(e.dataType)) { mixin(S_TRACE);
  1084. // XML????????
  1085. getSelectionFlagAndStep(_dragFlags, _dragSteps);
  1086. e.data = bytesFromXML(getXML(_dir, _dragFlags, _dragSteps));
  1087. }
  1088. }
  1089. override void dragFinished(DragSourceEvent e) { mixin(S_TRACE);
  1090. if (e.detail == DND.DROP_MOVE) { mixin(S_TRACE);
  1091. foreach (flag; _dragFlags) { mixin(S_TRACE);
  1092. flag.parent.remove(flag);
  1093. }
  1094. foreach (step; _dragSteps) { mixin(S_TRACE);
  1095. step.parent.remove(step);
  1096. }
  1097. refresh();
  1098. _comm.delFlagAndStep.call(_dragFlags, _dragSteps);
  1099. _comm.refreshToolBar();
  1100. }
  1101. _dragFlags.length = 0;
  1102. _dragSteps.length = 0;
  1103. }
  1104. }
  1105. void flagsSelected() { mixin(S_TRACE);
  1106. refreshStatusLine();
  1107. _comm.refreshToolBar();
  1108. }
  1109. class SListener : SelectionAdapter {
  1110. override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  1111. flagsSelected();
  1112. }
  1113. }
  1114. class DListener : DisposeListener {
  1115. override void widgetDisposed(DisposeEvent e) { mixin(S_TRACE);
  1116. _comm.refUseCount.remove(&__refreshUseCount);
  1117. _comm.replText.remove(&refresh);
  1118. }
  1119. }
  1120. void nameEditEnd(TableItem selItm, int column, string text) { mixin(S_TRACE);
  1121. text = FlagDir.validName(text);
  1122. auto itms = flags.getSelection();
  1123. itms = itms.remove(selItm);
  1124. itms.insertInPlace(0, selItm);
  1125. Flag[] refF;
  1126. Step[] refS;
  1127. int[] indices;
  1128. string[] oldNames;
  1129. string[] oldNamesF;
  1130. string[] oldNamesS;
  1131. FlagId[] oldFID;
  1132. StepId[] oldSID;
  1133. foreach (itm; itms) { mixin(S_TRACE);
  1134. auto f = cast(Flag)itm.getData();
  1135. if (f) { mixin(S_TRACE);
  1136. indices ~= indexOf(f.parent, f);
  1137. oldNamesF ~= f.name;
  1138. oldNames ~= f.name;
  1139. refF ~= f;
  1140. oldFID ~= toFlagId(f.path);
  1141. }
  1142. auto s = cast(Step)itm.getData();
  1143. if (s) { mixin(S_TRACE);
  1144. indices ~= indexOf(s.parent, s);
  1145. oldNamesS ~= s.name;
  1146. oldNames ~= s.name;
  1147. refS ~= s;
  1148. oldSID ~= toStepId(s.path);
  1149. }
  1150. }
  1151. if (indices.length) { mixin(S_TRACE);
  1152. auto newNamesF = _dir.createNewFlagNames(text, refF.length, oldNamesF);
  1153. auto newNamesS = _dir.createNewStepNames(text, refS.length, oldNamesS);
  1154. bool changed = false;
  1155. changed |= setNames(refF, newNamesF, uc);
  1156. changed |= setNames(refS, newNamesS, uc);
  1157. if (changed) { mixin(S_TRACE);
  1158. storeEdit(indices, oldNames);
  1159. refresh();
  1160. _comm.refFlagAndStep.call(refF, refS);
  1161. }
  1162. }
  1163. _comm.refreshToolBar();
  1164. }
  1165. static bool setNames(F)(F[] refVals, in string[] newNames, UseCounter uc) { mixin(S_TRACE);
  1166. // ???????????????????????????
  1167. if (!refVals.length) return false;
  1168. auto dir = refVals[0].parent;
  1169. auto newSet = new HashSet!string;
  1170. foreach (name; newNames) newSet.add(name.toLower());
  1171. auto tempSet = new HashSet!string;
  1172. foreach (i; 0..refVals.length) { mixin(S_TRACE);
  1173. auto name = createNewName("temp", (string name) { mixin(S_TRACE);
  1174. if (!dir.canAppend!F(name)) return false;
  1175. name = name.toLower();
  1176. return !newSet.contains(name) && !tempSet.contains(name);
  1177. });
  1178. tempSet.add(name);
  1179. }
  1180. string[] oldNames;
  1181. foreach (i, tempName; tempSet.toArray()) { mixin(S_TRACE);
  1182. auto f = refVals[i];
  1183. oldNames ~= f.name;
  1184. auto oldID = F.toID(f.path);
  1185. f.name = tempName;
  1186. uc.change(oldID, F.toID(f.path), false);
  1187. }
  1188. bool changed = false;
  1189. foreach (i, name; newNames) { mixin(S_TRACE);
  1190. auto f = refVals[i];
  1191. auto oldID = F.toID(f.path);
  1192. f.name = name;
  1193. uc.change(oldID, F.toID(f.path), false);
  1194. if (oldNames[i] != name) changed = true;
  1195. }
  1196. return changed;
  1197. }
  1198. void initCombo(TableItem itm, int column, out string[] strs, out string str) { mixin(S_TRACE);
  1199. auto f = cast(Flag) itm.getData();
  1200. if (f) { mixin(S_TRACE);
  1201. strs = [f.on, f.off];
  1202. str = f.onOff ? f.on : f.off;
  1203. return;
  1204. }
  1205. auto s = cast(Step) itm.getData();
  1206. if (s) { mixin(S_TRACE);
  1207. foreach (i, v; s.values) { mixin(S_TRACE);
  1208. strs ~= v;
  1209. if (i == s.select) { mixin(S_TRACE);
  1210. str = v;
  1211. }
  1212. }
  1213. return;
  1214. }
  1215. }
  1216. void initEditEnd(TableItem selItm, int column, Combo combo) { mixin(S_TRACE);
  1217. int i = combo.getSelectionIndex();
  1218. if (-1 == i) return;
  1219. auto selFlag = cast(Flag)selItm.getData();
  1220. auto selStep = cast(Step)selItm.getData();
  1221. auto itms = flags.getSelection();
  1222. itms = itms.remove(selItm);
  1223. itms.insertInPlace(0, selItm);
  1224. Flag[] refF;
  1225. Step[] refS;
  1226. int[] indices;
  1227. string[] oldNames;
  1228. int[] oldValues;
  1229. foreach (itm; itms) { mixin(S_TRACE);
  1230. auto f = cast(Flag)itm.getData();
  1231. if (selFlag && f) { mixin(S_TRACE);
  1232. if (f.onOff == (0 == i)) continue;
  1233. indices ~= indexOf(f.parent, f);
  1234. oldNames ~= f.name;
  1235. oldValues ~= f.onOff ? 0 : 1;
  1236. f.onOff = 0 == i;
  1237. itm.setText(column, f.onOff ? f.on : f.off);
  1238. refF ~= f;
  1239. }
  1240. auto s = cast(Step)itm.getData();
  1241. if (selStep && s) { mixin(S_TRACE);
  1242. if (s.select == i) continue;
  1243. indices ~= indexOf(s.parent, s);
  1244. oldNames ~= s.name;
  1245. oldValues ~= s.select;
  1246. s.select(i);
  1247. itm.setText(column, s.value);
  1248. refS ~= s;
  1249. }
  1250. }
  1251. if (indices.length) { mixin(S_TRACE);
  1252. storeEdit(indices, oldNames, oldValues);
  1253. _comm.refFlagAndStep.call(refF, refS);
  1254. }
  1255. _comm.refreshToolBar();
  1256. }
  1257. class Dispose : DisposeListener {
  1258. override void widgetDisposed(DisposeEvent e) { mixin(S_TRACE);
  1259. foreach (dlg; _editDlgsF.values) { mixin(S_TRACE);
  1260. dlg.forceCancel();
  1261. }
  1262. foreach (dlg; _editDlgsS.values) { mixin(S_TRACE);
  1263. dlg.forceCancel();
  1264. }
  1265. }
  1266. }
  1267. @property
  1268. Shell dlgParShl() { mixin(S_TRACE);
  1269. if (flags && !flags.isDisposed()) return flags.getShell();
  1270. return _comm.mainWin.shell.getShell();
  1271. }
  1272. void selectAll() { mixin(S_TRACE);
  1273. foreach (i; 0 .. flags.getItemCount()) { mixin(S_TRACE);
  1274. flags.select(i);
  1275. }
  1276. flagsSelected();
  1277. }
  1278. void copyFlagTree(bool onOff) { mixin(S_TRACE);
  1279. auto c = createSetFlagTree(selectionFlags, onOff);
  1280. if (!c) return;
  1281. XMLtoCB(prop, _comm.clipboard, c.toXML(new XMLOption(prop.sys)));
  1282. _comm.refreshToolBar();
  1283. }
  1284. void copyStepTree(int value) { mixin(S_TRACE);
  1285. auto c = createSetStepTree(selectionSteps, value);
  1286. if (!c) return;
  1287. XMLtoCB(prop, _comm.clipboard, c.toXML(new XMLOption(prop.sys)));
  1288. _comm.refreshToolBar();
  1289. }
  1290. void copyInitTree() { mixin(S_TRACE);
  1291. Flag[] fs;
  1292. Step[] ss;
  1293. getSelectionFlagAndStep(fs, ss);
  1294. auto c = createInitVariablesTree(fs, ss);
  1295. if (!c) return;
  1296. XMLtoCB(prop, _comm.clipboard, c.toXML(new XMLOption(prop.sys)));
  1297. _comm.refreshToolBar();
  1298. }
  1299. void copyFlagReverseTree() { mixin(S_TRACE);
  1300. auto c = createReverseFlagTree(selectionFlags);
  1301. if (!c) return;
  1302. XMLtoCB(prop, _comm.clipboard, c.toXML(new XMLOption(prop.sys)));
  1303. _comm.refreshToolBar();
  1304. }
  1305. void copyStepUpTree() { mixin(S_TRACE);
  1306. auto c = createSetStepUpTree(selectionSteps);
  1307. if (!c) return;
  1308. XMLtoCB(prop, _comm.clipboard, c.toXML(new XMLOption(prop.sys)));
  1309. _comm.refreshToolBar();
  1310. }
  1311. void copyStepDownTree() { mixin(S_TRACE);
  1312. auto c = createSetStepDownTree(selectionSteps);
  1313. if (!c) return;
  1314. XMLtoCB(prop, _comm.clipboard, c.toXML(new XMLOption(prop.sys)));
  1315. _comm.refreshToolBar();
  1316. }
  1317. void copyVariablePath() { mixin(S_TRACE);
  1318. if (0 == flags.getSelectionCount()) return;
  1319. char[] buf;
  1320. foreach (itm; flags.getSelection()) { mixin(S_TRACE);
  1321. if (buf.length) buf ~= .newline;
  1322. auto f = cast(Flag)itm.getData();
  1323. if (f) buf ~= f.path;
  1324. auto s = cast(Step)itm.getData();
  1325. if (s) buf ~= s.path;
  1326. assert (f || s);
  1327. }
  1328. _comm.clipboard.setContents([new ArrayWrapperString(buf)],
  1329. [TextTransfer.getInstance()]);
  1330. _comm.refreshToolBar();
  1331. }
  1332. public:
  1333. this (Commons comm, Props prop, UndoManager undo) { mixin(S_TRACE);
  1334. _undo = undo;
  1335. _comm = comm;
  1336. this.prop = prop;
  1337. }
  1338. /// ????????????
  1339. /// Params:
  1340. /// parent = ????????
  1341. Control createControl(Composite parent, Composite incSearchParent) { mixin(S_TRACE);
  1342. _comp = new Composite(parent, SWT.NONE);
  1343. _comp.setLayout(new FillLayout);
  1344. flags = new Table(_comp, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION);
  1345. flags.setHeaderVisible(true);
  1346. auto nameCol = new TableColumn(flags, SWT.NULL);
  1347. nameCol.setText(prop.msgs.flagName);
  1348. saveColumnWidth!("prop.var.etc.flagNameColumn")(prop, nameCol);
  1349. auto initCol = new TableColumn(flags, SWT.NULL);
  1350. initCol.setText(prop.msgs.flagInit);
  1351. saveColumnWidth!("prop.var.etc.flagInitColumn")(prop, initCol);
  1352. auto countCol = new TableColumn(flags, SWT.NULL);
  1353. countCol.setText(prop.msgs.flagCount);
  1354. saveColumnWidth!("prop.var.etc.flagCountColumn")(prop, countCol);
  1355. updateIncSearchParent(incSearchParent);
  1356. flags.addKeyListener(new KListener);
  1357. flags.addMouseListener(new MListener);
  1358. auto menu = new Menu(flags.getShell(), SWT.POP_UP);
  1359. createMenuItem(_comm, menu, MenuID.IncSearch, &incSearch, null);
  1360. new MenuItem(menu, SWT.SEPARATOR);
  1361. createMenuItem(_comm, menu, MenuID.EditProp, &edit, &canEdit);
  1362. new MenuItem(menu, SWT.SEPARATOR);
  1363. createMenuItem(_comm, menu, MenuID.NewFlag, &createFlag, () => _dir !is null);
  1364. createMenuItem(_comm, menu, MenuID.NewStep, &createStep, () => _dir !is null);
  1365. new MenuItem(menu, SWT.SEPARATOR);
  1366. createMenuItem(_comm, menu, MenuID.Undo, &this.undo, &_undo.canUndo);
  1367. createMenuItem(_comm, menu, MenuID.Redo, &this.redo, &_undo.canRedo);
  1368. new MenuItem(menu, SWT.SEPARATOR);
  1369. appendMenuTCPD(_comm, menu, this, true, true, true, true, true);
  1370. new MenuItem(menu, SWT.SEPARATOR);
  1371. createMenuItem(_comm, menu, MenuID.SelectAll, &selectAll, () => flags.getItemCount() && flags.getSelectionCount() != flags.getItemCount());
  1372. new MenuItem(menu, SWT.SEPARATOR);
  1373. void delegate() dlg = null;
  1374. auto evt = createMenuItem(_comm, menu, MenuID.CreateVariableEventTree, dlg, () => 0 < flags.getSelectionCount(), SWT.CASCADE);
  1375. auto mEvt = new Menu(parent.getShell(), SWT.DROP_DOWN);
  1376. evt.setMenu(mEvt);
  1377. createMenuItem(_comm, mEvt, MenuID.InitVariablesTree, &copyInitTree, () => 0 < flags.getSelectionCount());
  1378. new MenuItem(mEvt, SWT.SEPARATOR);
  1379. createMenuItem2(_comm, mEvt, MenuProps.buildMenu(prop.msgs.contentName(CType.REVERSE_FLAG), "R", "", false), prop.images.content(CType.REVERSE_FLAG), &copyFlagReverseTree, () => 0 < selectionFlags.length);
  1380. new MenuItem(mEvt, SWT.SEPARATOR);
  1381. createMenuItem2(_comm, mEvt, MenuProps.buildMenu(prop.msgs.setFlagTrue, "T", "", false), prop.images.content(CType.SET_FLAG), () => copyFlagTree(true), () => 0 < selectionFlags.length);
  1382. createMenuItem2(_comm, mEvt, MenuProps.buildMenu(prop.msgs.setFlagFalse, "F", "", false), prop.images.content(CType.SET_FLAG), () => copyFlagTree(false), () => 0 < selectionFlags.length);
  1383. new MenuItem(mEvt, SWT.SEPARATOR);
  1384. createMenuItem2(_comm, mEvt, MenuProps.buildMenu(prop.msgs.contentName(CType.SET_STEP_UP), "U", "", false), prop.images.content(CType.SET_STEP_UP), &copyStepUpTree, () => 0 < selectionSteps.length);
  1385. createMenuItem2(_comm, mEvt, MenuProps.buildMenu(prop.msgs.contentName(CType.SET_STEP_DOWN), "D", "", false), prop.images.content(CType.SET_STEP_DOWN), &copyStepDownTree, () => 0 < selectionSteps.length);
  1386. new MenuItem(mEvt, SWT.SEPARATOR);
  1387. void ssValue(uint i) { mixin(S_TRACE);
  1388. string mnemonic = i < 10 ? .text(i) : "";
  1389. createMenuItem2(_comm, mEvt, MenuProps.buildMenu(.tryFormat(prop.msgs.setStepValue, .tryFormat(prop.msgs.dlgTxtStep, i)), mnemonic, "", false), prop.images.content(CType.SET_STEP), () => copyStepTree(i), () => 0 < selectionSteps.length);
  1390. }
  1391. foreach (i; 0..prop.looks.stepMaxCount) { mixin(S_TRACE);
  1392. ssValue(i);
  1393. }
  1394. new MenuItem(menu, SWT.SEPARATOR);
  1395. createMenuItem(_comm, menu, MenuID.FindID, &replaceID, &canReplaceID);
  1396. new MenuItem(menu, SWT.SEPARATOR);
  1397. createMenuItem(_comm, menu, MenuID.CopyVariablePath, &copyVariablePath, () => 0 < flags.getSelectionCount());
  1398. flags.setMenu(menu);
  1399. auto ds = new DragSource(flags, DND.DROP_MOVE | DND.DROP_COPY);
  1400. ds.setTransfer([XMLBytesTransfer.getInstance()]);
  1401. ds.addDragListener(new FlagDragListener);
  1402. _comm.refUseCount.add(&__refreshUseCount);
  1403. _comm.replText.add(&refresh);
  1404. flags.addSelectionListener(new SListener);
  1405. flags.addDisposeListener(new DListener);
  1406. new TableTextEdit(_comm, prop, flags, 0, &nameEditEnd, null);
  1407. new TableComboEdit!Combo(_comm, prop, flags, 1, &initCombo, &initEditEnd, null);
  1408. _comp.addDisposeListener(new Dispose);
  1409. return _comp;
  1410. }
  1411. void updateIncSearchParent(Composite incSearchParent) {
  1412. auto matchers = [
  1413. AdditionMatcher(MenuProps.buildMenu(.objName!Step(prop), "S", "", false), (o) => cast(Step)o !is null),
  1414. AdditionMatcher(MenuProps.buildMenu(.objName!Flag(prop), "F", "", false), (o) => cast(Flag)o !is null),
  1415. ];
  1416. _incSearch = new IncSearch(_comm, incSearchParent, matchers);
  1417. _incSearch.modEvent ~= &refresh;
  1418. }
  1419. private Composite _comp = null;
  1420. @property
  1421. Control widget() {return _comp;}
  1422. @property
  1423. package Flag[] dragFlags() {return _dragFlags;}
  1424. @property
  1425. package Step[] dragSteps() {return _dragSteps;}
  1426. private void refreshStatusLine() { mixin(S_TRACE);
  1427. string s = "";
  1428. void put(lazy string name, size_t count) { mixin(S_TRACE);
  1429. if (!count) return;
  1430. if (s.length) s ~= " ";
  1431. s ~= .tryFormat(prop.msgs.flagStatus, name, count);
  1432. }
  1433. if (_dir) { mixin(S_TRACE);
  1434. put(prop.msgs.flag, _dir.flags.length);
  1435. put(prop.msgs.step, _dir.steps.length);
  1436. }
  1437. Flag[] selFlags;
  1438. Step[] selSteps;
  1439. getSelectionFlagAndStep(selFlags, selSteps);
  1440. if (selFlags.length || selSteps.length) { mixin(S_TRACE);
  1441. s = .tryFormat(prop.msgs.flagStatusSel, s, selFlags.length + selSteps.length);
  1442. }
  1443. _statusLine = s;
  1444. _comm.setStatusLine(flags, _statusLine);
  1445. }
  1446. @property
  1447. string statusLine() {return _statusLine;}
  1448. private void __refreshUseCount() { mixin(S_TRACE);
  1449. foreach (itm; flags.getItems()) { mixin(S_TRACE);
  1450. if (cast(Flag) itm.getData()) { mixin(S_TRACE);
  1451. itm.setText(2, to!(string)(uc.flag.get(toFlagId((cast(Flag) itm.getData()).path))));
  1452. } else { mixin(S_TRACE);
  1453. assert (cast(Step) itm.getData());
  1454. itm.setText(2, to!(string)(uc.step.get(toStepId((cast(Step) itm.getData()).path))));
  1455. }
  1456. }
  1457. }
  1458. void refresh() { mixin(S_TRACE);
  1459. refresh(null);
  1460. }
  1461. void refresh(in Object selObj) { mixin(S_TRACE);
  1462. if (!flags || flags.isDisposed()) return;
  1463. if (_dir) { mixin(S_TRACE);
  1464. const(Object)[] sels;
  1465. if (selObj) { mixin(S_TRACE);
  1466. sels ~= selObj;
  1467. } else { mixin(S_TRACE);
  1468. foreach (itm; flags.getSelection()) { mixin(S_TRACE);
  1469. sels ~= itm.getData();
  1470. }
  1471. }
  1472. flags.deselectAll();
  1473. _dir.sortSteps();
  1474. _dir.sortFlags();
  1475. refreshFlags();
  1476. foreach (i, itm; flags.getItems()) { mixin(S_TRACE);
  1477. if (.contains(sels, itm.getData())) { mixin(S_TRACE);
  1478. flags.select(i);
  1479. }
  1480. }
  1481. if (selObj) { mixin(S_TRACE);
  1482. flags.showSelection();
  1483. }
  1484. }
  1485. refreshStatusLine();
  1486. }
  1487. /// ???????????index?
  1488. @property
  1489. int[] selected() { mixin(S_TRACE);
  1490. if (flags && !flags.isDisposed()) { mixin(S_TRACE);
  1491. return flags.getSelectionIndices();
  1492. }
  1493. return [];
  1494. }
  1495. /// ??????????????????????
  1496. int[] selectedItems(out Flag[] fs, out Step[] ss) { mixin(S_TRACE);
  1497. if (flags && !flags.isDisposed()) { mixin(S_TRACE);
  1498. auto indices = flags.getSelectionIndices();
  1499. foreach (i; indices) { mixin(S_TRACE);
  1500. auto o = flags.getItem(i).getData();
  1501. auto f = cast(Flag) o;
  1502. if (f) fs ~= f;
  1503. auto s = cast(Step) o;
  1504. if (s) ss ~= s;
  1505. }
  1506. return indices;
  1507. }
  1508. return [];
  1509. }
  1510. /// ditto
  1511. @property
  1512. Flag[] selectionFlags() { mixin(S_TRACE);
  1513. Flag[] fs;
  1514. Step[] ss;
  1515. getSelectionFlagAndStep(fs, ss);
  1516. return fs;
  1517. }
  1518. /// ditto
  1519. @property
  1520. Step[] selectionSteps() { mixin(S_TRACE);
  1521. Flag[] fs;
  1522. Step[] ss;
  1523. getSelectionFlagAndStep(fs, ss);
  1524. return ss;
  1525. }
  1526. /// ditto
  1527. @property
  1528. string[] selectionFlagNames() { mixin(S_TRACE);
  1529. string[] r;
  1530. foreach (f; selectionFlags) { mixin(S_TRACE);
  1531. r ~= f.name;
  1532. }
  1533. return r;
  1534. }
  1535. /// ditto
  1536. @property
  1537. string[] selectionStepNames() { mixin(S_TRACE);
  1538. string[] r;
  1539. foreach (f; selectionSteps) { mixin(S_TRACE);
  1540. r ~= f.name;
  1541. }
  1542. return r;
  1543. }
  1544. /// ???????????????????
  1545. /// ??????????????????????
  1546. void createFlag() { mixin(S_TRACE);
  1547. editFlag(_dir, null);
  1548. }
  1549. /// ????????????????????
  1550. /// ???????????????????????
  1551. void createStep() { mixin(S_TRACE);
  1552. editStep(_dir, null);
  1553. }
  1554. /// ?????????????????????
  1555. void edit() { mixin(S_TRACE);
  1556. if (_dir !is null) { mixin(S_TRACE);
  1557. foreach (index; flags.getSelectionIndices()) { mixin(S_TRACE);
  1558. if (auto step = cast(Step)flags.getItem(index).getData()) { mixin(S_TRACE);
  1559. editStep(step.parent, step);
  1560. } else if (auto flag = cast(Flag)flags.getItem(index).getData()) { mixin(S_TRACE);
  1561. editFlag(flag.parent, flag);
  1562. } else assert (0);
  1563. }
  1564. }
  1565. }
  1566. @property
  1567. bool canEdit() { mixin(S_TRACE);
  1568. return flags.getSelectionIndex() != -1;
  1569. }
  1570. /// ?????????????????
  1571. void edit(Flag flag) { mixin(S_TRACE);
  1572. enforce(flag.parent is dir);
  1573. editFlag(flag.parent, flag);
  1574. }
  1575. /// ??????????????????
  1576. void edit(Step step) { mixin(S_TRACE);
  1577. enforce(step.parent is dir);
  1578. editStep(step.parent, step);
  1579. }
  1580. /// ?????????????????
  1581. /// Params:
  1582. /// dir = ???????
  1583. void setDir(FlagDir dir, bool forceRefresh = false) { mixin(S_TRACE);
  1584. if (!forceRefresh && _dir is dir) return;
  1585. foreach (dlg; _editDlgsF.values) { mixin(S_TRACE);
  1586. dlg.forceCancel();
  1587. }
  1588. foreach (dlg; _editDlgsS.values) { mixin(S_TRACE);
  1589. dlg.forceCancel();
  1590. }
  1591. _dir = dir;
  1592. refresh();
  1593. }
  1594. /// Returns: ????????????
  1595. @property
  1596. FlagDir dir() { mixin(S_TRACE);
  1597. return _dir;
  1598. }
  1599. private void selectImpl(Object flag, bool deselect) { mixin(S_TRACE);
  1600. if (deselect) flags.deselectAll();
  1601. foreach (i, itm; flags.getItems()) { mixin(S_TRACE);
  1602. if (itm.getData() is flag) { mixin(S_TRACE);
  1603. flags.select(i);
  1604. break;
  1605. }
  1606. }
  1607. flags.showSelection();
  1608. _comm.refreshToolBar();
  1609. }
  1610. /// ?????????
  1611. void select(Flag flag, bool deselect) { mixin(S_TRACE);
  1612. selectImpl(flag, deselect);
  1613. }
  1614. /// ??????????
  1615. void select(Step step, bool deselect) { mixin(S_TRACE);
  1616. selectImpl(step, deselect);
  1617. }
  1618. void deselectAll() { mixin(S_TRACE);
  1619. flags.deselectAll();
  1620. }
  1621. /// ????????????
  1622. void dispose() { mixin(S_TRACE);
  1623. if (flags !is null) { mixin(S_TRACE);
  1624. flags.dispose();
  1625. }
  1626. }
  1627. /// ??????????????
  1628. /// Params:
  1629. /// uc = ?????????
  1630. @property
  1631. void useCounter(UseCounter uc) { mixin(S_TRACE);
  1632. this.uc = uc;
  1633. }
  1634. override {
  1635. void cut(SelectionEvent se) { mixin(S_TRACE);
  1636. if (!_dir) return;
  1637. copy(se);
  1638. del(se);
  1639. }
  1640. void copy(SelectionEvent se) { mixin(S_TRACE);
  1641. if (!_dir) return;
  1642. Flag[] fs;
  1643. Step[] ss;
  1644. if (getSelectionFlagAndStep(fs, ss)) { mixin(S_TRACE);
  1645. XMLtoCB(prop, _comm.clipboard, getXML(_dir, fs, ss));
  1646. _comm.refreshToolBar();
  1647. }
  1648. }
  1649. void paste(SelectionEvent se) { mixin(S_TRACE);
  1650. if (!_dir) return;
  1651. auto c = CBtoXML(_comm.clipboard);
  1652. if (c) { mixin(S_TRACE);
  1653. try { mixin(S_TRACE);
  1654. string newPath;
  1655. string rootId;
  1656. Flag[string] cFlags;
  1657. Step[string] cSteps;
  1658. auto selsF = selectionFlagNames;
  1659. auto selsS = selectionStepNames;
  1660. auto ver = new XMLInfo(prop.sys, LATEST_VERSION);
  1661. if (_dir.appendFromXML(c, ver, true, false, cFlags, cSteps, newPath, rootId)) { mixin(S_TRACE);
  1662. string[] flagName;
  1663. string[] stepName;
  1664. foreach (f; cFlags) { mixin(S_TRACE);
  1665. flagName ~= f.name;
  1666. }
  1667. foreach (s; cSteps) { mixin(S_TRACE);
  1668. stepName ~= s.name;
  1669. }
  1670. storeInsert(selsF, selsS, flagName, stepName);
  1671. refresh();
  1672. _comm.refFlagAndStep.call(cFlags.values, cSteps.values);
  1673. _comm.refreshToolBar();
  1674. }
  1675. } catch (Exception e) {
  1676. debugln(e);
  1677. }
  1678. }
  1679. }
  1680. void del(SelectionEvent se) { mixin(S_TRACE);
  1681. if (!_dir) return;
  1682. auto selsF = selectionFlagNames;
  1683. auto selsS = selectionStepNames;
  1684. Flag[] fs;
  1685. Step[] ss;
  1686. foreach (itm; flags.getSelection()) { mixin(S_TRACE);
  1687. auto data = itm.getData();
  1688. auto flag = cast(Flag) data;
  1689. if (flag) { mixin(S_TRACE);
  1690. fs ~= flag;
  1691. _dir.remove(flag);
  1692. }
  1693. auto step = cast(Step) data;
  1694. if (step) { mixin(S_TRACE);
  1695. ss ~= step;
  1696. _dir.remove(step);
  1697. }
  1698. }
  1699. storeDelete(selsF, selsS, fs, ss);
  1700. _comm.delFlagAndStep.call(fs, ss);
  1701. refresh();
  1702. _comm.refreshToolBar();
  1703. }
  1704. void clone(SelectionEvent se) { mixin(S_TRACE);
  1705. _comm.clipboard.memoryMode = true;
  1706. scope (exit) _comm.clipboard.memoryMode = false;
  1707. copy(se);
  1708. paste(se);
  1709. }
  1710. @property
  1711. bool canDoTCPD() { mixin(S_TRACE);
  1712. return _comm.summary && flags.isFocusControl();
  1713. }
  1714. @property
  1715. bool canDoT() { mixin(S_TRACE);
  1716. return flags.getSelectionIndex() != -1;
  1717. }
  1718. @property
  1719. bool canDoC() { mixin(S_TRACE);
  1720. return canDoT;
  1721. }
  1722. @property
  1723. bool canDoP() { mixin(S_TRACE);
  1724. return _comm.summary !is null && CBisXML(_comm.clipboard);
  1725. }
  1726. @property
  1727. bool canDoD() { mixin(S_TRACE);
  1728. return canDoT;
  1729. }
  1730. @property
  1731. bool canDoClone() { mixin(S_TRACE);
  1732. return canDoC;
  1733. }
  1734. }
  1735. void undo() { mixin(S_TRACE);
  1736. _undo.undo();
  1737. _comm.refreshToolBar();
  1738. }
  1739. void redo() { mixin(S_TRACE);
  1740. _undo.redo();
  1741. _comm.refreshToolBar();
  1742. }
  1743. void replaceID() {
  1744. auto index = flags.getSelectionIndex();
  1745. if (index <= -1) return;
  1746. auto data = flags.getItem(index).getData();
  1747. if (auto f = cast(Flag)data) _comm.replaceID(toFlagId(f.path), true);
  1748. if (auto f = cast(Step)data) _comm.replaceID(toStepId(f.path), true);
  1749. }
  1750. @property
  1751. bool canReplaceID() {
  1752. auto index = flags.getSelectionIndex();
  1753. if (index <= -1) return false;
  1754. auto data = flags.getItem(index).getData();
  1755. return cast(Flag)data || cast(Step)data;
  1756. }
  1757. @property
  1758. string[] openedCWXPath() { mixin(S_TRACE);
  1759. string[] r;
  1760. Flag[] fs;
  1761. Step[] ss;
  1762. getSelectionFlagAndStep(fs, ss);
  1763. foreach (f; fs) { mixin(S_TRACE);
  1764. r ~= f.cwxPath(true);
  1765. }
  1766. foreach (s; ss) { mixin(S_TRACE);
  1767. r ~= s.cwxPath(true);
  1768. }
  1769. return r;
  1770. }
  1771. }