PageRenderTime 53ms CodeModel.GetById 7ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://bitbucket.org/k4nagatsuki/cwxeditor
D | 2683 lines | 2500 code | 135 blank | 48 comment | 359 complexity | c7da1b3e317cf6cd1cc458f9f702851d MD5 | raw file
Possible License(s): LGPL-2.1
  1. module cwx.editor.gui.dwt.messageutils;
  2. import cwx.utils;
  3. import cwx.types;
  4. import cwx.event;
  5. import cwx.summary;
  6. import cwx.skin;
  7. import cwx.xml;
  8. import cwx.flag;
  9. import cwx.path;
  10. import cwx.structs;
  11. import cwx.msgutils;
  12. import cwx.menu;
  13. import cwx.types;
  14. import cwx.imagesize;
  15. import cwx.system;
  16. import cwx.editor.gui.dwt.dprops;
  17. import cwx.editor.gui.dwt.dskin;
  18. import cwx.editor.gui.dwt.dutils;
  19. import cwx.editor.gui.dwt.commons;
  20. import cwx.editor.gui.dwt.centerlayout;
  21. import cwx.editor.gui.dwt.customtext;
  22. import cwx.editor.gui.dwt.customtable;
  23. import cwx.editor.gui.dwt.imageselect;
  24. import cwx.editor.gui.dwt.materialselect;
  25. import cwx.editor.gui.dwt.absdialog;
  26. import cwx.editor.gui.dwt.eventdialog;
  27. import cwx.editor.gui.dwt.xmlbytestransfer;
  28. import cwx.editor.gui.dwt.undo;
  29. import cwx.editor.gui.dwt.splitpane;
  30. import cwx.editor.gui.dwt.properties;
  31. import cwx.editor.gui.dwt.absdialog;
  32. import cwx.editor.gui.dwt.dmenu;
  33. import cwx.editor.gui.dwt.couponview;
  34. import cwx.editor.gui.dwt.chooser;
  35. import std.array;
  36. import std.utf;
  37. import std.string;
  38. import std.datetime;
  39. import std.conv;
  40. import std.exception;
  41. import org.eclipse.swt.all;
  42. import java.lang.all;
  43. /// ??????????????????????????????
  44. class AbstractMessageDialog : EventDialog {
  45. private KeyDownFilter _kdFilter;
  46. private MsgPreviewWindow _previewWin = null;
  47. private MsgPreview _preview = null;
  48. private UndoManager _undo;
  49. private class SelPrev : SelectionAdapter {
  50. override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  51. auto btn = cast(Button) e.widget;
  52. if (btn.getSelection()) { mixin(S_TRACE);
  53. auto s = wrapReturnCode(text);
  54. if (_previewWin) { mixin(S_TRACE);
  55. if (_previewWin.isVisible()) return;
  56. _previewWin.text(selectedTalker, "", s);
  57. _previewWin.open();
  58. } else { mixin(S_TRACE);
  59. if (rightGroup.isVisible()) return;
  60. _preview.text(selectedTalker, imgPath, s);
  61. setPreviewLData(true);
  62. }
  63. } else { mixin(S_TRACE);
  64. if (_previewWin) { mixin(S_TRACE);
  65. if (!_previewWin.isVisible()) return;
  66. _previewWin.close();
  67. } else { mixin(S_TRACE);
  68. if (!rightGroup.isVisible()) return;
  69. setPreviewLData(false);
  70. }
  71. }
  72. }
  73. }
  74. private void setPreviewLData(bool visible, bool regWin = true) { mixin(S_TRACE);
  75. bool oVisible = rightGroup.isVisible();
  76. assert (_preview);
  77. rightGroup.setVisible(visible);
  78. int pvw;
  79. if (!visible) { mixin(S_TRACE);
  80. pvw = rightGroup.getSize().x;
  81. }
  82. int w = visible ? prop.looks.messageBounds.width : 0;
  83. int h = 0;
  84. rightGroupSize(w, h);
  85. if (getShell().isVisible()) getShell().setRedraw(false);
  86. scope (exit) {
  87. if (getShell().isVisible()) getShell().setRedraw(true);
  88. }
  89. if (regWin && oVisible != visible) { mixin(S_TRACE);
  90. auto ws = getShell().getSize();
  91. if (visible) { mixin(S_TRACE);
  92. pvw = rightGroup.getSize().x;
  93. }
  94. if (visible) { mixin(S_TRACE);
  95. ws.x += pvw;
  96. } else { mixin(S_TRACE);
  97. ws.x -= pvw;
  98. }
  99. getShell().setSize(ws);
  100. }
  101. }
  102. private class Dispose : DisposeListener {
  103. override void widgetDisposed(DisposeEvent e) { mixin(S_TRACE);
  104. comm.refMenu.remove(&refMenu);
  105. comm.refUndoMax.remove(&refUndoMax);
  106. getShell().getDisplay().removeFilter(SWT.KeyDown, _kdFilter);
  107. if (_preview) { mixin(S_TRACE);
  108. if (type is CType.TALK_MESSAGE) { mixin(S_TRACE);
  109. prop.var.etc.showMessagePreview = _preview.isVisible();
  110. } else if (type is CType.TALK_DIALOG) { mixin(S_TRACE);
  111. prop.var.etc.showDialogPreview = _preview.isVisible();
  112. } else assert (0);
  113. }
  114. }
  115. }
  116. private class KeyDownFilter : Listener {
  117. this () { mixin(S_TRACE);
  118. refMenu(MenuID.Undo);
  119. refMenu(MenuID.Redo);
  120. }
  121. override void handleEvent(Event e) { mixin(S_TRACE);
  122. auto c = cast(Control) e.widget;
  123. if (!c || c.getShell() !is getShell()) return;
  124. if (!canHookKeyDown(c)) return;
  125. if (cast(Text) c) return;
  126. if (eqAcc(_undoAcc, e.keyCode, e.character, e.stateMask)) { mixin(S_TRACE);
  127. _undo.undo();
  128. e.doit = false;
  129. } else if (eqAcc(_redoAcc, e.keyCode, e.character, e.stateMask)) { mixin(S_TRACE);
  130. _undo.redo();
  131. e.doit = false;
  132. }
  133. }
  134. }
  135. protected bool canHookKeyDown(Control fc) { mixin(S_TRACE);
  136. return !_preview || !_preview.focusInValues;
  137. }
  138. private int _undoAcc;
  139. private int _redoAcc;
  140. private void refMenu(MenuID id) { mixin(S_TRACE);
  141. if (id == MenuID.Undo) _undoAcc = convertAccelerator(prop.buildMenu(MenuID.Undo));
  142. if (id == MenuID.Redo) _redoAcc = convertAccelerator(prop.buildMenu(MenuID.Redo));
  143. }
  144. private void refUndoMax() { mixin(S_TRACE);
  145. _undo.max = prop.var.etc.undoMaxEtc;
  146. }
  147. protected void initPreview(Composite area, WSize size) { mixin(S_TRACE);
  148. auto aComp = addition();
  149. aComp.setLayout(new GridLayout(1, true));
  150. auto prev = new Button(aComp, SWT.TOGGLE);
  151. prev.setText(prop.msgs.messagePreview);
  152. bool show;
  153. if (type is CType.TALK_MESSAGE) { mixin(S_TRACE);
  154. show = prop.var.etc.showMessagePreview;
  155. } else if (type is CType.TALK_DIALOG) { mixin(S_TRACE);
  156. show = prop.var.etc.showDialogPreview;
  157. } else assert (0);
  158. prev.setSelection(show);
  159. prev.addSelectionListener(new SelPrev);
  160. if (prop.var.etc.floatMessagePreview) { mixin(S_TRACE);
  161. _previewWin = new MsgPreviewWindow(getShell(), comm, prop, summ, prev, size);
  162. } else { mixin(S_TRACE);
  163. _preview = new MsgPreview(rightGroup, comm, prop, summ);
  164. rightGroup.setLayout(zeroGridLayout(1, false));
  165. _preview.setLayoutData(new GridData(GridData.FILL_BOTH));
  166. setPreviewLData(show, false);
  167. }
  168. refreshPreview();
  169. }
  170. this (Commons comm, Props prop, Shell shell, Summary summ, CType type, Content parent, Content evt, DSize size) { mixin(S_TRACE);
  171. super (comm, prop, shell, summ, type, parent, evt, true, size, false, !prop.var.etc.floatMessagePreview);
  172. _undo = new UndoManager(prop.var.etc.undoMaxEtc);
  173. }
  174. override
  175. protected void opened() { mixin(S_TRACE);
  176. if (!_previewWin) return;
  177. if (type is CType.TALK_MESSAGE) { mixin(S_TRACE);
  178. if (prop.var.etc.showMessagePreview) _previewWin.open();
  179. closeEvent ~= { mixin(S_TRACE);
  180. prop.var.etc.showMessagePreview = _previewWin.isVisible();
  181. };
  182. } else if (type is CType.TALK_DIALOG) { mixin(S_TRACE);
  183. if (prop.var.etc.showDialogPreview) _previewWin.open();
  184. closeEvent ~= { mixin(S_TRACE);
  185. prop.var.etc.showDialogPreview = _previewWin.isVisible();
  186. };
  187. } else assert (0);
  188. }
  189. protected override void setup(Composite area) { mixin(S_TRACE);
  190. area.addDisposeListener(new Dispose);
  191. _kdFilter = new KeyDownFilter;
  192. area.getDisplay().addFilter(SWT.KeyDown, _kdFilter);
  193. comm.refMenu.add(&refMenu);
  194. comm.refUndoMax.add(&refUndoMax);
  195. }
  196. void refreshPreview() { mixin(S_TRACE);
  197. if (!_previewWin && !_preview) return;
  198. auto s = wrapReturnCode(text);
  199. if (_previewWin) { mixin(S_TRACE);
  200. _previewWin.text(selectedTalker, imgPath, s);
  201. _previewWin.refresh();
  202. } else { mixin(S_TRACE);
  203. _preview.text(selectedTalker, imgPath, s);
  204. _preview.refresh();
  205. }
  206. }
  207. @property
  208. abstract string text();
  209. @property
  210. abstract Talker selectedTalker();
  211. @property
  212. abstract string imgPath();
  213. }
  214. /// ????????????????
  215. class SpeakDialog : AbstractMessageDialog {
  216. private:
  217. class APData {
  218. int selDlg;
  219. SDialog[] dlgs;
  220. }
  221. Object readAPD(Object old) { mixin(S_TRACE);
  222. auto o = new APData;
  223. o.selDlg = _dlgsL.getSelectionIndex();
  224. foreach (d; _dlgs) { mixin(S_TRACE);
  225. o.dlgs ~= new SDialog(d);
  226. }
  227. return o;
  228. }
  229. void writeAPD(Object o) { mixin(S_TRACE);
  230. bool oldIgnoreMod = ignoreMod;
  231. ignoreMod = true;
  232. scope (exit) ignoreMod = oldIgnoreMod;
  233. auto apd = cast(APData)o;
  234. assert (apd);
  235. foreach (i, d; apd.dlgs) { mixin(S_TRACE);
  236. _dlgs[i] = new SDialog(d);
  237. }
  238. refreshDlgList();
  239. _dlgsL.select(apd.selDlg);
  240. selectChanged();
  241. }
  242. class SUndo : Undo {
  243. private SDialog[] _dlgs;
  244. private int _selDlg;
  245. this () { mixin(S_TRACE);
  246. save();
  247. }
  248. private void save() { mixin(S_TRACE);
  249. _dlgs = [];
  250. foreach (d; this.outer._dlgs) { mixin(S_TRACE);
  251. _dlgs ~= new SDialog(d);
  252. }
  253. _selDlg = _dlgsL.getSelectionIndex();
  254. }
  255. private void impl() { mixin(S_TRACE);
  256. auto dlgs = _dlgs;
  257. int selDlg = _selDlg;
  258. save();
  259. this.outer._dlgs = [];
  260. foreach (dlg; dlgs) { mixin(S_TRACE);
  261. this.outer._dlgs ~= new SDialog(dlg);
  262. }
  263. refreshDlgList();
  264. _dlgsL.select(selDlg);
  265. selectChanged();
  266. }
  267. override void undo() {impl();}
  268. override void redo() {impl();}
  269. override void dispose() { mixin(S_TRACE);
  270. // Nothing
  271. }
  272. }
  273. void storeEdit() { mixin(S_TRACE);
  274. _undo ~= new SUndo;
  275. }
  276. void updateValue() { mixin(S_TRACE);
  277. int max = _initValue.getSelection();
  278. int min = max;
  279. foreach (cp; _couponView.coupons) { mixin(S_TRACE);
  280. if (cp.value < 0) { mixin(S_TRACE);
  281. min -= cp.value;
  282. } else { mixin(S_TRACE);
  283. max += cp.value;
  284. }
  285. }
  286. if (0 >= min) { mixin(S_TRACE);
  287. _couponView.toolTip = .tryFormat(prop.msgs.valuedTalkerMaxMinLess0, max, min);
  288. } else { mixin(S_TRACE);
  289. _couponView.toolTip = .tryFormat(prop.msgs.valuedTalkerMaxMin, max, min);
  290. }
  291. }
  292. override
  293. protected void refreshWarning() { mixin(S_TRACE);
  294. string[] ws;
  295. if (prop.targetVersion("1.50")) { mixin(S_TRACE);
  296. if (Talker.VALUED is selectedTalker) { mixin(S_TRACE);
  297. ws ~= prop.msgs.warningValuedTalker;
  298. }
  299. }
  300. warning = ws;
  301. }
  302. string _id;
  303. Combo _talkers;
  304. SDialog[] _dlgs;
  305. Table _dlgsL;
  306. Text _rCoupons;
  307. Combo _rCouponsList;
  308. FixedWidthText _text;
  309. TextMenuModify _textTM, _rCouponsTM;
  310. CouponView!(CVType.Valued) _couponView;
  311. Spinner _initValue;
  312. protected override bool canHookKeyDown(Control fc) { mixin(S_TRACE);
  313. return super.canHookKeyDown(fc) && !isDescendant(_couponView, fc);
  314. }
  315. void selectChanged() { mixin(S_TRACE);
  316. bool oldIgnoreMod = ignoreMod;
  317. ignoreMod = true;
  318. scope (exit) ignoreMod = oldIgnoreMod;
  319. auto dlg = _dlgs[_dlgsL.getSelectionIndex()];
  320. string rcs;
  321. foreach (rc; dlg.rCoupons) { mixin(S_TRACE);
  322. rcs ~= rc;
  323. rcs ~= '\n';
  324. }
  325. _rCoupons.setText(rcs);
  326. _text.setText(dlg.text);
  327. auto len = dlg.text.length;
  328. _text.widget.setSelection(len, len);
  329. refreshPreview();
  330. comm.refreshToolBar();
  331. }
  332. void createDialog(SDialog dlg) { mixin(S_TRACE);
  333. insertDialog(dlg, _dlgsL.getSelectionIndex());
  334. }
  335. void createDialog() { mixin(S_TRACE);
  336. createDialog(new SDialog);
  337. }
  338. void insertDialog(SDialog dlg, int index, bool store = true) { mixin(S_TRACE);
  339. if (store) storeEdit();
  340. if (index < 0) index = _dlgs.length;
  341. _dlgs = _dlgs[0 .. index] ~ dlg ~ _dlgs[index .. $];
  342. auto itm = new TableItem(_dlgsL, SWT.NONE, index);
  343. itm.setImage(prop.images.content(CType.TALK_DIALOG));
  344. _dlgsL.setSelection([itm]);
  345. _dlgsL.showSelection();
  346. selectChanged();
  347. applyEnabled();
  348. }
  349. void deleteDialog(int index, bool store = true) { mixin(S_TRACE);
  350. if (index < 0 || _dlgs.length <= 1) return;
  351. if (store) storeEdit();
  352. bool sel = _dlgsL.getSelectionIndex() == index;
  353. _dlgs = _dlgs[0 .. index] ~ _dlgs[index + 1 .. $];
  354. _dlgsL.remove(index);
  355. if (sel) { mixin(S_TRACE);
  356. _dlgsL.select(index < _dlgs.length ? index : _dlgs.length - 1);
  357. selectChanged();
  358. } else { mixin(S_TRACE);
  359. comm.refreshToolBar();
  360. }
  361. applyEnabled();
  362. }
  363. void deleteDialogSel() { mixin(S_TRACE);
  364. deleteDialog(_dlgsL.getSelectionIndex());
  365. }
  366. void overDialog() { mixin(S_TRACE);
  367. int index = _dlgsL.getSelectionIndex();
  368. if (index > 0) { mixin(S_TRACE);
  369. _dlgsL.select(index - 1);
  370. selectChanged();
  371. }
  372. }
  373. void underDialog() { mixin(S_TRACE);
  374. int index = _dlgsL.getSelectionIndex();
  375. if (index + 1 < _dlgs.length) { mixin(S_TRACE);
  376. _dlgsL.select(index + 1);
  377. selectChanged();
  378. }
  379. }
  380. void up() { mixin(S_TRACE);
  381. int index = _dlgsL.getSelectionIndex();
  382. if (index > 0) { mixin(S_TRACE);
  383. storeEdit();
  384. auto temp = _dlgs[index - 1];
  385. _dlgs[index - 1] = _dlgs[index];
  386. _dlgs[index] = temp;
  387. auto tempL = _dlgsL.getItem(index - 1).getText();
  388. _dlgsL.getItem(index - 1).setText(_dlgsL.getItem(index).getText());
  389. _dlgsL.getItem(index).setText(tempL);
  390. _dlgsL.select(index - 1);
  391. applyEnabled();
  392. comm.refreshToolBar();
  393. }
  394. }
  395. void down() { mixin(S_TRACE);
  396. int index = _dlgsL.getSelectionIndex();
  397. if (index + 1 < _dlgs.length) { mixin(S_TRACE);
  398. storeEdit();
  399. auto temp = _dlgs[index + 1];
  400. _dlgs[index + 1] = _dlgs[index];
  401. _dlgs[index] = temp;
  402. auto tempL = _dlgsL.getItem(index + 1).getText();
  403. _dlgsL.getItem(index + 1).setText(_dlgsL.getItem(index).getText());
  404. _dlgsL.getItem(index).setText(tempL);
  405. _dlgsL.select(index + 1);
  406. applyEnabled();
  407. comm.refreshToolBar();
  408. }
  409. }
  410. void copyToUpper() { mixin(S_TRACE);
  411. storeEdit();
  412. int index = _dlgsL.getSelectionIndex();
  413. string textL = _dlgsL.getItem(index).getText();
  414. string text = lastRet(wrapReturnCode(_text.getText()));
  415. for (int i = 0; i < index; i++) { mixin(S_TRACE);
  416. _dlgsL.getItem(i).setText(textL);
  417. _dlgs[i].text = text;
  418. }
  419. applyEnabled();
  420. comm.refreshToolBar();
  421. }
  422. void copyToLower() { mixin(S_TRACE);
  423. storeEdit();
  424. int index = _dlgsL.getSelectionIndex();
  425. string textL = _dlgsL.getItem(index).getText();
  426. string text = lastRet(wrapReturnCode(_text.getText()));
  427. for (int i = index + 1; i < _dlgs.length; i++) { mixin(S_TRACE);
  428. _dlgsL.getItem(i).setText(textL);
  429. _dlgs[i].text = text;
  430. }
  431. applyEnabled();
  432. comm.refreshToolBar();
  433. }
  434. void copyToDialogs() { mixin(S_TRACE);
  435. storeEdit();
  436. int index = _dlgsL.getSelectionIndex();
  437. string textL = _dlgsL.getItem(index).getText();
  438. string text = lastRet(wrapReturnCode(_text.getText()));
  439. foreach (i, dlg; _dlgs) { mixin(S_TRACE);
  440. if (i != index) { mixin(S_TRACE);
  441. _dlgsL.getItem(i).setText(textL);
  442. dlg.text = text;
  443. }
  444. }
  445. applyEnabled();
  446. comm.refreshToolBar();
  447. }
  448. void put(dchar put) { mixin(S_TRACE);
  449. putColor(_text, put);
  450. }
  451. void insert(string put) { mixin(S_TRACE);
  452. _text.insert(put);
  453. }
  454. void putText(SDialog dlg) { mixin(S_TRACE);
  455. dlg.text = lastRet(wrapReturnCode(_text.getText()));
  456. }
  457. void putRCoupons(SDialog dlg) { mixin(S_TRACE);
  458. string[] rcs;
  459. foreach (rc; splitLines!string(_rCoupons.getText())) { mixin(S_TRACE);
  460. if (rc.length > 0) { mixin(S_TRACE);
  461. rcs ~= rc;
  462. }
  463. }
  464. dlg.rCoupons = rcs;
  465. }
  466. void updateTalker() { mixin(S_TRACE);
  467. _couponView.enabled = (Talker.VALUED is selectedTalker);
  468. _initValue.setEnabled(_couponView.enabled);
  469. comm.refreshToolBar();
  470. }
  471. class SelL : SelectionAdapter {
  472. override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  473. selectChanged();
  474. }
  475. }
  476. class SelectTalker : SelectionAdapter {
  477. override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  478. refreshPreview();
  479. refreshWarning();
  480. updateTalker();
  481. }
  482. }
  483. private void refreshDlgList(int index) { mixin(S_TRACE);
  484. string text = wrapReturnCode(_dlgs[index].text).singleLine;
  485. // FIXME: ""?setText???Argument cannot be null
  486. if (text == "") text = " ";
  487. _dlgsL.getItem(index).setText(0, text);
  488. }
  489. class ModL : ModifyListener {
  490. override void modifyText(ModifyEvent e) { mixin(S_TRACE);
  491. if (_textTM && _rCouponsTM && !_textTM.inProc() && !_rCouponsTM.inProc()) { mixin(S_TRACE);
  492. putText(_dlgs[_dlgsL.getSelectionIndex()]);
  493. }
  494. refreshDlgList(_dlgsL.getSelectionIndex());
  495. refreshPreview();
  496. }
  497. }
  498. class ModRC : ModifyListener {
  499. override void modifyText(ModifyEvent e) { mixin(S_TRACE);
  500. if (_textTM && _rCouponsTM && !_textTM.inProc() && !_rCouponsTM.inProc()) { mixin(S_TRACE);
  501. putRCoupons(_dlgs[_dlgsL.getSelectionIndex()]);
  502. }
  503. }
  504. }
  505. @property
  506. SDialog selection() { mixin(S_TRACE);
  507. int index = _dlgsL.getSelectionIndex();
  508. return index >= 0 ? _dlgs[index] : null;
  509. }
  510. class DialogsTCPD : TCPD {
  511. void cut(SelectionEvent se) { mixin(S_TRACE);
  512. if (_dlgsL.getItemCount() > 1 && selection) { mixin(S_TRACE);
  513. copy(se);
  514. del(se);
  515. }
  516. }
  517. void copy(SelectionEvent se) { mixin(S_TRACE);
  518. auto d = selection;
  519. if (d) { mixin(S_TRACE);
  520. XMLtoCB(prop, comm.clipboard, d.toNode().text);
  521. comm.refreshToolBar();
  522. }
  523. }
  524. void paste(SelectionEvent se) { mixin(S_TRACE);
  525. auto xml = CBtoXML(comm.clipboard);
  526. if (xml) { mixin(S_TRACE);
  527. try { mixin(S_TRACE);
  528. auto node = XNode.parse(xml);
  529. if (node.name == SDialog.XML_NAME) { mixin(S_TRACE);
  530. auto ver = new XMLInfo(prop.sys, LATEST_VERSION);
  531. createDialog(SDialog.createFromNode(node, ver));
  532. }
  533. } catch (Exception e) {
  534. debugln(e);
  535. }
  536. }
  537. }
  538. void del(SelectionEvent se) {deleteDialogSel();}
  539. void clone(SelectionEvent se) { mixin(S_TRACE);
  540. comm.clipboard.memoryMode = true;
  541. scope (exit) comm.clipboard.memoryMode = false;
  542. copy(se);
  543. paste(se);
  544. }
  545. @property bool canDoTCPD() {return _dlgsL.isFocusControl();}
  546. @property bool canDoT() {return _dlgsL.getSelectionIndex() > 0;}
  547. @property bool canDoC() {return canDoT;}
  548. @property bool canDoP() {return CBisXML(comm.clipboard);}
  549. @property bool canDoD() {return canDoT;}
  550. @property bool canDoClone() {return canDoC;}
  551. }
  552. class DDropListener : DropTargetAdapter {
  553. override void dragEnter(DropTargetEvent e){ mixin(S_TRACE);
  554. e.detail = DND.DROP_MOVE;
  555. }
  556. override void dragOver(DropTargetEvent e){ mixin(S_TRACE);
  557. e.detail = DND.DROP_MOVE;
  558. }
  559. override void drop(DropTargetEvent e){ mixin(S_TRACE);
  560. if (!isXMLBytes(e.data)) return;
  561. e.detail = DND.DROP_NONE;
  562. string xml = bytesToXML(e.data);
  563. try { mixin(S_TRACE);
  564. auto node = XNode.parse(xml);
  565. if (node.name != SDialog.XML_NAME) return;
  566. storeEdit();
  567. scope p = (cast(DropTarget) e.getSource()).getControl().toControl(e.x, e.y);
  568. auto t = _dlgsL.getItem(p);
  569. int index = t ? _dlgsL.indexOf(t) : _dlgsL.getItemCount();
  570. auto ver = new XMLInfo(prop.sys, LATEST_VERSION);
  571. insertDialog(SDialog.createFromNode(node, ver), index, false);
  572. if (_id == node.attr("paneId", false)) { mixin(S_TRACE);
  573. e.detail = DND.DROP_MOVE;
  574. }
  575. } catch {}
  576. }
  577. }
  578. class DDragListener : DragSourceAdapter {
  579. private TableItem _itm;
  580. override void dragStart(DragSourceEvent e) { mixin(S_TRACE);
  581. e.doit = (cast(DragSource) e.getSource()).getControl().isFocusControl();
  582. }
  583. override void dragSetData(DragSourceEvent e){ mixin(S_TRACE);
  584. if (XMLBytesTransfer.getInstance().isSupportedType(e.dataType)) { mixin(S_TRACE);
  585. auto c = cast(Table) (cast(DragSource) e.getSource()).getControl();
  586. int index = c.getSelectionIndex();
  587. if (index >= 0) { mixin(S_TRACE);
  588. auto d = _dlgs[index];
  589. auto node = d.toNode();
  590. node.newAttr("paneId", _id);
  591. e.data = bytesFromXML(node.text);
  592. _itm = c.getItem(index);
  593. }
  594. }
  595. }
  596. override void dragFinished(DragSourceEvent e) { mixin(S_TRACE);
  597. if (e.detail == DND.DROP_MOVE) { mixin(S_TRACE);
  598. deleteDialog(_dlgsL.indexOf(_itm), false);
  599. }
  600. }
  601. }
  602. protected override void refSkin() { mixin(S_TRACE);
  603. _text.font = dwtData(prop.looks.messageFont(summ.legacy));
  604. }
  605. void refreshDlgList() { mixin(S_TRACE);
  606. bool oldIgnoreMod = ignoreMod;
  607. ignoreMod = true;
  608. scope (exit) ignoreMod = oldIgnoreMod;
  609. int selIndex = _dlgsL.getSelectionIndex();
  610. int topIndex = _dlgsL.getTopIndex();
  611. _dlgsL.removeAll();
  612. foreach (dlg; _dlgs) { mixin(S_TRACE);
  613. auto itm = new TableItem(_dlgsL, SWT.NONE);
  614. itm.setImage(prop.images.content(CType.TALK_DIALOG));
  615. string text = dlg.text.singleLine;
  616. // FIXME: ""?setText???Argument cannot be null
  617. itm.setText(text.length > 0 ? text : " ");
  618. }
  619. if (selIndex < 0 || _dlgs.length <= selIndex) { mixin(S_TRACE);
  620. _dlgsL.select(0);
  621. } else { mixin(S_TRACE);
  622. _dlgsL.select(selIndex);
  623. _dlgsL.setTopIndex(topIndex);
  624. }
  625. if (selIndex != _dlgsL.getSelectionIndex()) { mixin(S_TRACE);
  626. selectChanged();
  627. } else { mixin(S_TRACE);
  628. comm.refreshToolBar();
  629. }
  630. }
  631. class DisposeLeftSash : DisposeListener {
  632. override void widgetDisposed(DisposeEvent e) { mixin(S_TRACE);
  633. auto sash = cast(SplitPane) e.widget;
  634. auto ws = sash.getWeights();
  635. prop.var.etc.talkLeftSashL = ws[0];
  636. prop.var.etc.talkLeftSashR = ws[1];
  637. }
  638. }
  639. class DisposeMainSash : DisposeListener {
  640. override void widgetDisposed(DisposeEvent e) { mixin(S_TRACE);
  641. auto sash = cast(SplitPane) e.widget;
  642. auto ws = sash.getWeights();
  643. prop.var.etc.talkMainSashL = ws[0];
  644. prop.var.etc.talkMainSashR = ws[1];
  645. }
  646. }
  647. private class KeyDownFilter : Listener {
  648. this () { mixin(S_TRACE);
  649. refMenu(MenuID.OverDialog);
  650. refMenu(MenuID.UnderDialog);
  651. }
  652. override void handleEvent(Event e) { mixin(S_TRACE);
  653. auto c = cast(Control) e.widget;
  654. if (!c || c.getShell() !is getShell()) return;
  655. if (_dlgsL is c) return;
  656. if (eqAcc(_overAcc, e.keyCode, e.character, e.stateMask)) { mixin(S_TRACE);
  657. overDialog();
  658. e.doit = false;
  659. } else if (eqAcc(_underAcc, e.keyCode, e.character, e.stateMask)) { mixin(S_TRACE);
  660. underDialog();
  661. e.doit = false;
  662. }
  663. }
  664. }
  665. private int _overAcc;
  666. private int _underAcc;
  667. private void refMenu(MenuID id) { mixin(S_TRACE);
  668. if (id == MenuID.OverDialog) _overAcc = convertAccelerator(prop.buildMenu(MenuID.OverDialog));
  669. if (id == MenuID.UnderDialog) _underAcc = convertAccelerator(prop.buildMenu(MenuID.UnderDialog));
  670. }
  671. public:
  672. this (Commons comm, Props prop, Shell shell, Summary summ, Content parent, Content evt) { mixin(S_TRACE);
  673. _id = format("%08X", &this) ~ "-" ~ to!(string)(Clock.currTime());
  674. super(comm, prop, shell, summ, CType.TALK_DIALOG, parent, evt, prop.var.speakDlg);
  675. }
  676. override
  677. bool openCWXPath(string path, bool shellActivate) { mixin(S_TRACE);
  678. auto cate = cpcategory(path);
  679. if ("dialog" == cate) { mixin(S_TRACE);
  680. auto index = cpindex(path);
  681. if (index >= _dlgsL.getItemCount()) return false;
  682. _dlgsL.select(index);
  683. selectChanged();
  684. .forceFocus(_dlgsL, shellActivate);
  685. path = cpbottom(path);
  686. return cpempty(path);
  687. }
  688. return super.openCWXPath(path, shellActivate);
  689. }
  690. @property
  691. override
  692. string text() { mixin(S_TRACE);
  693. return wrapReturnCode(_text.getText());
  694. }
  695. @property
  696. override
  697. Talker selectedTalker() { mixin(S_TRACE);
  698. switch (_talkers.getSelectionIndex()) {
  699. case 0: return Talker.SELECTED;
  700. case 1: return Talker.UNSELECTED;
  701. case 2: return Talker.RANDOM;
  702. case 3: return Talker.VALUED;
  703. default: assert (0);
  704. }
  705. }
  706. @property
  707. override
  708. string imgPath() { mixin(S_TRACE);
  709. return "";
  710. }
  711. protected:
  712. override void setup(Composite area) { mixin(S_TRACE);
  713. super.setup(area);
  714. area.setLayout(windowGridLayout(1, true));
  715. auto sash = new SplitPane(area, SWT.HORIZONTAL);
  716. sash.setLayoutData(new GridData(GridData.FILL_BOTH));
  717. auto left = new Composite(sash, SWT.NONE);
  718. left.setLayout(zeroMarginGridLayout(1, true));
  719. { mixin(S_TRACE);
  720. auto grp = new Group(left, SWT.NONE);
  721. grp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  722. grp.setText(prop.msgs.talker);
  723. grp.setLayout(new GridLayout(1, true));
  724. _talkers = new Combo(grp, SWT.READ_ONLY | SWT.DROP_DOWN | SWT.BORDER);
  725. mod(_talkers);
  726. _talkers.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  727. _talkers.add(prop.msgs.talkerName(Talker.SELECTED));
  728. _talkers.add(prop.msgs.talkerName(Talker.UNSELECTED));
  729. _talkers.add(prop.msgs.talkerName(Talker.RANDOM));
  730. _talkers.add(prop.msgs.talkerName(Talker.VALUED));
  731. _talkers.addSelectionListener(new SelectTalker);
  732. }
  733. auto leftSash = new SplitPane(left, SWT.VERTICAL);
  734. leftSash.setLayoutData(new GridData(GridData.FILL_BOTH));
  735. auto skin = comm.skin;
  736. { mixin(S_TRACE);
  737. auto grp = new Group(leftSash, SWT.NONE);
  738. grp.setText(prop.msgs.toneCoupons);
  739. grp.setLayout(new GridLayout(1, true));
  740. Control tp;
  741. if (evt) { mixin(S_TRACE);
  742. tp = createTalkerPane2(grp, comm, prop, summ, evt.dialogs[0].rCoupons, _rCoupons, _rCouponsList);
  743. } else { mixin(S_TRACE);
  744. tp = createTalkerPane2(grp, comm, prop, summ, [], _rCoupons, _rCouponsList);
  745. }
  746. mod(_rCoupons);
  747. _rCoupons.addModifyListener(new ModRC);
  748. tp.setLayoutData(new GridData(GridData.FILL_BOTH));
  749. }
  750. { mixin(S_TRACE);
  751. auto grp = new Group(leftSash, SWT.NONE);
  752. grp.setText(prop.msgs.valued);
  753. grp.setLayout(new GridLayout(2, false));
  754. auto lbl = new Label(grp, SWT.NONE);
  755. lbl.setText(prop.msgs.initValue);
  756. _initValue = new Spinner(grp, SWT.BORDER);
  757. initSpinner(_initValue);
  758. mod(_initValue);
  759. _initValue.setMinimum(cast(int) prop.var.etc.couponValueMax * -1);
  760. _initValue.setMaximum(prop.var.etc.couponValueMax);
  761. _initValue.setSelection(1);
  762. _initValue.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  763. .listener(_initValue, SWT.Selection, &updateValue);
  764. _couponView = new CouponView!(CVType.Valued)(comm, summ, grp, SWT.NONE, &catchMod);
  765. mod(_couponView);
  766. auto gd = new GridData(GridData.FILL_BOTH);
  767. gd.horizontalSpan = 2;
  768. _couponView.setLayoutData(gd);
  769. _couponView.modEvent ~= &updateValue;
  770. }
  771. auto right = new Composite(sash, SWT.NONE);
  772. right.setLayout(zeroMarginGridLayout(2, false));
  773. { mixin(S_TRACE);
  774. _dlgsL = new Table(right, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER | SWT.V_SCROLL);
  775. new FullTableColumn(_dlgsL, SWT.NONE);
  776. auto gd = new GridData(GridData.FILL_BOTH);
  777. gd.widthHint = 0;
  778. gd.heightHint = 0;
  779. _dlgsL.setLayoutData(gd);
  780. _dlgsL.addSelectionListener(new SelL);
  781. auto drag = new DragSource(_dlgsL, DND.DROP_MOVE | DND.DROP_COPY);
  782. drag.setTransfer([XMLBytesTransfer.getInstance()]);
  783. drag.addDragListener(new DDragListener);
  784. auto drop = new DropTarget(_dlgsL, DND.DROP_DEFAULT | DND.DROP_MOVE | DND.DROP_COPY);
  785. drop.setTransfer([XMLBytesTransfer.getInstance()]);
  786. drop.addDropListener(new DDropListener);
  787. auto menu = new Menu(_dlgsL);
  788. createMenuItem(comm, menu, MenuID.Undo, {_undo.undo();}, &_undo.canUndo);
  789. createMenuItem(comm, menu, MenuID.Redo, {_undo.redo();}, &_undo.canRedo);
  790. new MenuItem(menu, SWT.SEPARATOR);
  791. createMenuItem(comm, menu, MenuID.Up, &up, () => _dlgsL.getSelectionIndex() != -1 && 0 < _dlgsL.getSelectionIndex());
  792. createMenuItem(comm, menu, MenuID.Down, &down, () => _dlgsL.getSelectionIndex() != -1 && _dlgsL.getSelectionIndex() + 1 < _dlgsL.getItemCount());
  793. new MenuItem(menu, SWT.SEPARATOR);
  794. createMenuItem(comm, menu, MenuID.OverDialog, &overDialog, () => _dlgsL.getSelectionIndex() != -1 && 0 < _dlgsL.getSelectionIndex());
  795. createMenuItem(comm, menu, MenuID.UnderDialog, &underDialog, () => _dlgsL.getSelectionIndex() != -1 && _dlgsL.getSelectionIndex() + 1 < _dlgsL.getItemCount());
  796. new MenuItem(menu, SWT.SEPARATOR);
  797. appendMenuTCPD(comm, menu, new DialogsTCPD, true, true, true, true, true);
  798. _dlgsL.setMenu(menu);
  799. auto bar = new ToolBar(right, SWT.FLAT | SWT.VERTICAL);
  800. comm.put(bar);
  801. bar.setLayoutData(new GridData(GridData.FILL_VERTICAL));
  802. bar.addListener(SWT.Traverse, new class Listener {
  803. override void handleEvent(Event e) {e.doit = true;}
  804. });
  805. bar.addListener(SWT.KeyDown, new class Listener {
  806. override void handleEvent(Event e) {e.doit = true;}
  807. });
  808. createToolItem2(comm, bar, prop.msgs.createDialog, prop.images.createDialog, &createDialog, null);
  809. createToolItem2(comm, bar, prop.msgs.deleteDialog, prop.images.deleteDialog, &deleteDialogSel, () => _dlgsL.getItemCount() > 1 && _dlgsL.getSelectionIndex() != -1);
  810. new ToolItem(bar, SWT.SEPARATOR);
  811. createToolItem(comm, bar, MenuID.Up, &up, () => _dlgsL.getSelectionIndex() != -1 && 0 < _dlgsL.getSelectionIndex());
  812. createToolItem(comm, bar, MenuID.Down, &down, () => _dlgsL.getSelectionIndex() != -1 && _dlgsL.getSelectionIndex() + 1 < _dlgsL.getItemCount());
  813. new ToolItem(bar, SWT.SEPARATOR);
  814. createToolItem2(comm, bar, prop.msgs.copyToDialogs, prop.images.copyToDialogs, &copyToDialogs, () => _dlgsL.getSelectionIndex() != -1 && _dlgsL.getItemCount() > 1);
  815. createToolItem2(comm, bar, prop.msgs.copyToUpper, prop.images.copyToUpper, &copyToUpper, () => _dlgsL.getSelectionIndex() != -1 && 0 < _dlgsL.getSelectionIndex());
  816. createToolItem2(comm, bar, prop.msgs.copyToLower, prop.images.copyToLower, &copyToLower, () => _dlgsL.getSelectionIndex() != -1 && _dlgsL.getSelectionIndex() + 1 < _dlgsL.getItemCount());
  817. }
  818. { mixin(S_TRACE);
  819. auto msgComp = new Composite(right, SWT.NONE);
  820. auto gd = new GridData(GridData.FILL_HORIZONTAL);
  821. gd.horizontalSpan = 2;
  822. msgComp.setLayoutData(gd);
  823. msgComp.setLayout(new CenterLayout(SWT.HORIZONTAL | SWT.VERTICAL, 0));
  824. _text = createMessagePane(comm, prop, true, msgComp, summ);
  825. mod(_text.widget);
  826. _text.widget.setLayoutData(_text.computeTextBaseSize(prop.looks.messageLine));
  827. _text.widget.addModifyListener(new ModL);
  828. }
  829. { mixin(S_TRACE);
  830. auto bar = createSCharBar(comm, area, &insert, &put, prop, skin);
  831. bar.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  832. }
  833. { mixin(S_TRACE);
  834. auto bar = createSkinSCharBar(comm, area, &insert, prop, skin);
  835. bar.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  836. }
  837. { mixin(S_TRACE);
  838. auto bar = createFlagStepBar(area, &insert, comm, prop);
  839. bar.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  840. }
  841. leftSash.setWeights([prop.var.etc.talkLeftSashL, prop.var.etc.talkLeftSashR]);
  842. leftSash.addDisposeListener(new DisposeLeftSash);
  843. sash.setWeights([prop.var.etc.talkMainSashL, prop.var.etc.talkMainSashR]);
  844. sash.addDisposeListener(new DisposeMainSash);
  845. auto kdFilter = new KeyDownFilter;
  846. area.getDisplay().addFilter(SWT.KeyDown, kdFilter);
  847. comm.refMenu.add(&refMenu);
  848. .listener(area, SWT.Dispose, { mixin(S_TRACE);
  849. area.getDisplay().removeFilter(SWT.KeyDown, kdFilter);
  850. comm.refMenu.remove(&refMenu);
  851. });
  852. ignoreMod = true;
  853. scope (exit) ignoreMod = false;
  854. if (evt) { mixin(S_TRACE);
  855. switch (evt.talkerNC) {
  856. case Talker.SELECTED:
  857. _talkers.select(0);
  858. break;
  859. case Talker.UNSELECTED:
  860. _talkers.select(1);
  861. break;
  862. case Talker.RANDOM:
  863. _talkers.select(2);
  864. break;
  865. case Talker.VALUED:
  866. _talkers.select(3);
  867. break;
  868. default:
  869. _talkers.select(0);
  870. }
  871. foreach (dlg; evt.dialogs) { mixin(S_TRACE);
  872. _dlgs ~= new SDialog(dlg.text, dlg.rCoupons);
  873. }
  874. _couponView.coupons = evt.coupons;
  875. _initValue.setSelection(evt.initValue);
  876. } else { mixin(S_TRACE);
  877. _talkers.select(0);
  878. _dlgs = [new SDialog];
  879. }
  880. refreshDlgList();
  881. _textTM = createTextMenu!Text(comm, prop, _rCoupons, &catchMod, _undo, TMAppendData(&readAPD, &writeAPD));
  882. _rCouponsTM = createTextMenu!Text(comm, prop, _text.widget, &catchMod, _undo, TMAppendData(&readAPD, &writeAPD));
  883. initPreview(area, prop.var.dlgPrev);
  884. updateValue();
  885. updateTalker();
  886. refreshWarning();
  887. }
  888. override bool apply() { mixin(S_TRACE);
  889. if (!evt) evt = new Content(CType.TALK_DIALOG, "");
  890. evt.dialogs = _dlgs;
  891. evt.talkerNC = selectedTalker;
  892. if (Talker.VALUED is evt.talkerNC) { mixin(S_TRACE);
  893. evt.coupons = _couponView.coupons;
  894. evt.initValue = _initValue.getSelection();
  895. } else { mixin(S_TRACE);
  896. evt.coupons = [];
  897. evt.initValue = 0;
  898. }
  899. comm.refCoupons.call();
  900. return true;
  901. }
  902. }
  903. /// ???????????????????
  904. class MessageDialog : AbstractMessageDialog {
  905. private:
  906. CTabFolder _tabf;
  907. Composite _msgCompA, _msgCompB;
  908. FixedWidthText _text;
  909. ImageSelect!(MtType.CARD, Combo) _msel;
  910. override
  911. protected void refreshWarning() { mixin(S_TRACE);
  912. string[] ws;
  913. ws ~= _msel.warnings;
  914. warning = ws;
  915. }
  916. void tabChanged() { mixin(S_TRACE);
  917. switch (_tabf.getSelectionIndex()) {
  918. case 0:
  919. _text.num = prop.looks.messageImageLen;
  920. _text.widget.setParent(_msgCompA);
  921. break;
  922. case 1:
  923. _text.num = prop.looks.messageLen;
  924. _text.widget.setParent(_msgCompB);
  925. break;
  926. default: return;
  927. }
  928. _text.widget.setLayoutData(_text.computeTextBaseSize(prop.looks.messageLine));
  929. _text.widget.getParent().layout();
  930. if (0 == _tabf.getSelectionIndex()) { mixin(S_TRACE);
  931. _text.widget.getParent().getParent().layout();
  932. }
  933. refreshPreview();
  934. }
  935. class SL : SelectionAdapter {
  936. override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  937. tabChanged();
  938. }
  939. }
  940. class ModText : ModifyListener {
  941. override void modifyText(ModifyEvent e) { mixin(S_TRACE);
  942. refreshPreview();
  943. }
  944. }
  945. void put(dchar put) { mixin(S_TRACE);
  946. putColor(_text, put);
  947. }
  948. void insert(string put) { mixin(S_TRACE);
  949. _text.insert(put);
  950. }
  951. protected override void refSkin() { mixin(S_TRACE);
  952. _text.font = dwtData(prop.looks.messageFont(summ.legacy));
  953. }
  954. public:
  955. this (Commons comm, Props prop, Shell shell, Summary summ, Content parent, Content evt) { mixin(S_TRACE);
  956. super(comm, prop, shell, summ, CType.TALK_MESSAGE, parent, evt, prop.var.msgDlg);
  957. }
  958. void selectedTalkerParam(out Talker talker, out string imgPath) { mixin(S_TRACE);
  959. imgPath = "";
  960. switch (_tabf.getSelectionIndex()) {
  961. case 0:
  962. switch (_msel.dirsCombo.getSelectionIndex()) {
  963. case 0:
  964. talker = Talker.SELECTED;
  965. break;
  966. case 1:
  967. talker = Talker.UNSELECTED;
  968. break;
  969. case 2:
  970. talker = Talker.RANDOM;
  971. break;
  972. case 3:
  973. talker = Talker.CARD;
  974. break;
  975. default:
  976. talker = Talker.IMAGE;
  977. imgPath = _msel.image;
  978. }
  979. break;
  980. case 1:
  981. talker = Talker.NARRATION;
  982. break;
  983. default: assert (0);
  984. }
  985. }
  986. @property
  987. override Talker selectedTalker() { mixin(S_TRACE);
  988. Talker talker;
  989. string imgPath;
  990. selectedTalkerParam(talker, imgPath);
  991. return talker;
  992. }
  993. @property
  994. override string imgPath() { mixin(S_TRACE);
  995. Talker talker;
  996. string imgPath;
  997. selectedTalkerParam(talker, imgPath);
  998. return imgPath;
  999. }
  1000. @property
  1001. override string text() { mixin(S_TRACE);
  1002. return wrapReturnCode(_text.getText());
  1003. }
  1004. protected:
  1005. override void setup(Composite area) { mixin(S_TRACE);
  1006. super.setup(area);
  1007. area.setLayout(new GridLayout(1, true));
  1008. _tabf = new CTabFolder(area, SWT.BORDER);
  1009. mod(_tabf);
  1010. _tabf.setLayoutData(new GridData(GridData.FILL_BOTH));
  1011. auto skin = comm.skin;
  1012. { mixin(S_TRACE);
  1013. auto comp = new Composite(_tabf, SWT.NONE);
  1014. comp.setLayout(new GridLayout(2, false));
  1015. Control tp;
  1016. if (evt) { mixin(S_TRACE);
  1017. tp = createTalkerPane(comp, comm, prop, summ, evt.talkerC, evt.cardPath, _msel);
  1018. } else { mixin(S_TRACE);
  1019. tp = createTalkerPane(comp, comm, prop, summ, Talker.SELECTED, "", _msel);
  1020. }
  1021. mod(_msel);
  1022. _msel.modEvent ~= &refreshWarning;
  1023. _msel.cardMode = CardMode.Message;
  1024. tp.setLayoutData(new GridData(GridData.FILL_BOTH));
  1025. _msgCompA = new Composite(comp, SWT.NONE);
  1026. _msgCompA.setLayoutData(new GridData(GridData.FILL_VERTICAL));
  1027. _msgCompA.setLayout(new CenterLayout(SWT.HORIZONTAL | SWT.VERTICAL, 0));
  1028. _text = createMessagePane(comm, prop, true, _msgCompA, summ);
  1029. mod(_text.widget);
  1030. _text.widget.addModifyListener(new ModText);
  1031. createTextMenu!Text(comm, prop, _text.widget, &catchMod, _undo);
  1032. auto tab = new CTabItem(_tabf, SWT.NONE);
  1033. tab.setText(prop.msgs.imageMessage);
  1034. tab.setControl(comp);
  1035. }
  1036. { mixin(S_TRACE);
  1037. _msgCompB = new Composite(_tabf, SWT.NONE);
  1038. _msgCompB.setLayout(new CenterLayout);
  1039. auto tab = new CTabItem(_tabf, SWT.NONE);
  1040. tab.setText(prop.msgs.noImageMessage);
  1041. tab.setControl(_msgCompB);
  1042. }
  1043. { mixin(S_TRACE);
  1044. auto bar = createSCharBar(comm, area, &insert, &put, prop, skin);
  1045. bar.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  1046. }
  1047. { mixin(S_TRACE);
  1048. auto bar = createSkinSCharBar(comm, area, &insert, prop, skin);
  1049. bar.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  1050. }
  1051. { mixin(S_TRACE);
  1052. auto bar = createFlagStepBar(area, &insert, comm, prop);
  1053. bar.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  1054. }
  1055. _tabf.addSelectionListener(new SL);
  1056. ignoreMod = true;
  1057. scope (exit) ignoreMod = false;
  1058. _tabf.setSelection(0);
  1059. if (evt) { mixin(S_TRACE);
  1060. _text.setText(evt.text);
  1061. if (evt.talkerC == Talker.NARRATION) { mixin(S_TRACE);
  1062. _tabf.setSelection(1);
  1063. }
  1064. } else { mixin(S_TRACE);
  1065. _tabf.setSelection(1);
  1066. }
  1067. tabChanged();
  1068. initPreview(area, prop.var.msgPrev);
  1069. _msel.modEvent ~= &refreshPreview;
  1070. _msel.updateImageEvent ~= &refreshPreview;
  1071. }
  1072. override bool apply() { mixin(S_TRACE);
  1073. string text;
  1074. string path = "";
  1075. Talker talker;
  1076. selectedTalkerParam(talker, path);
  1077. text = lastRet(wrapReturnCode(_text.getText()));
  1078. if (!evt) evt = new Content(CType.TALK_MESSAGE, "");
  1079. evt.text = text;
  1080. evt.talkerC = talker;
  1081. evt.cardPath = path;
  1082. return true;
  1083. }
  1084. }
  1085. private Composite createTalkerPane2(Composite parent, Commons comm, Props prop, Summary summ,
  1086. string[] coupons, out Text couponList, out Combo couponCombo) { mixin(S_TRACE);
  1087. auto comp = new Composite(parent, SWT.NONE);
  1088. comp.setLayout(zeroMarginGridLayout(2, false));
  1089. couponCombo = createCouponCombo(comm, summ, comp, null, CouponComboType.Talker, "");
  1090. auto push = new Button(comp, SWT.PUSH);
  1091. auto skin = comm.skin;
  1092. { mixin(S_TRACE);
  1093. auto gd = new GridData(GridData.FILL_HORIZONTAL);
  1094. gd.widthHint = prop.var.etc.talkersWidth;
  1095. couponCombo.setLayoutData(gd);
  1096. push.setToolTipText(prop.msgs.setTalkerCoupon);
  1097. push.setImage(prop.images.setTalkerCoupon);
  1098. }
  1099. { mixin(S_TRACE);
  1100. couponList = new Text(comp, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL);
  1101. auto gd = new GridData(GridData.FILL_BOTH);
  1102. gd.horizontalSpan = 2;
  1103. couponList.setLayoutData(gd);
  1104. string buf;
  1105. foreach (coupon; coupons) { mixin(S_TRACE);
  1106. buf ~= coupon ~ "\n";
  1107. }
  1108. couponList.setText(buf);
  1109. push.addSelectionListener(new class SelectionAdapter {
  1110. private Combo _combo;
  1111. private Text _list;
  1112. this() { mixin(S_TRACE);
  1113. _combo = couponCombo;
  1114. _list = couponList;
  1115. }
  1116. override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  1117. if (_combo.getText().length > 0) { mixin(S_TRACE);
  1118. _list.setSelection(_list.getText().length, _list.getText().length);
  1119. string[] lines = splitLines!string(_list.getText());
  1120. if (lines.length > 0 && lines[$ - 1].length > 0) { mixin(S_TRACE);
  1121. _list.insert("\n");
  1122. }
  1123. _list.insert(_combo.getText() ~ "\n");
  1124. }
  1125. }
  1126. });
  1127. }
  1128. return comp;
  1129. }
  1130. private Composite createTalkerPane
  1131. (Composite parent, Commons comm, Props prop, Summary summ, Talker talker, string path,
  1132. out ImageSelect!(MtType.CARD, Combo) msel) { mixin(S_TRACE);
  1133. auto comp = new Composite(parent, SWT.NONE);
  1134. { mixin(S_TRACE);
  1135. comp.setLayout(zeroMarginGridLayout(1, true));
  1136. }
  1137. auto selected = prop.images.talker(Talker.SELECTED).getImageData();
  1138. auto unselected = prop.images.talker(Talker.UNSELECTED).getImageData();
  1139. auto random = prop.images.talker(Talker.RANDOM).getImageData();
  1140. ImageData createDefImage(size_t index) { mixin(S_TRACE);
  1141. switch (index) {
  1142. case 0:
  1143. // ???
  1144. return selected;
  1145. case 1:
  1146. // ?????
  1147. return unselected;
  1148. case 2:
  1149. // ????
  1150. return random;
  1151. case 3:
  1152. // ???
  1153. return menuCard(comm.skin);
  1154. default: assert (0);
  1155. }
  1156. }
  1157. string[] defs = [
  1158. prop.msgs.talkerName(Talker.SELECTED),
  1159. prop.msgs.talkerName(Talker.UNSELECTED),
  1160. prop.msgs.talkerName(Talker.RANDOM),
  1161. prop.msgs.talkerName(Talker.CARD)
  1162. ];
  1163. auto s = prop.looks.cardSize;
  1164. msel = new ImageSelect!(MtType.CARD, Combo)(comp, SWT.NONE, comm, prop, summ, s.width, s.height,
  1165. false, false, () => "", null, defs, &createDefImage);
  1166. auto gd = new GridData(GridData.FILL_BOTH);
  1167. msel.widget.setLayoutData(gd);
  1168. msel.image = path;
  1169. if (msel.image.length == 0) { mixin(S_TRACE);
  1170. switch (talker) {
  1171. case Talker.SELECTED:
  1172. msel.dirsCombo.select(0);
  1173. break;
  1174. case Talker.UNSELECTED:
  1175. msel.dirsCombo.select(1);
  1176. break;
  1177. case Talker.RANDOM:
  1178. msel.dirsCombo.select(2);
  1179. break;
  1180. case Talker.CARD:
  1181. msel.dirsCombo.select(3);
  1182. break;
  1183. default:
  1184. msel.dirsCombo.select(0);
  1185. }
  1186. }
  1187. return comp;
  1188. }
  1189. private class DisposeText : DisposeListener {
  1190. private Color _back, _fore;
  1191. this (Color back, Color fore) { mixin(S_TRACE);
  1192. _back = back;
  1193. _fore = fore;
  1194. }
  1195. override void widgetDisposed(DisposeEvent e) { mixin(S_TRACE);
  1196. _back.dispose();
  1197. _fore.dispose();
  1198. }
  1199. }
  1200. private FixedWidthText createMessagePane(Commons comm, Props prop, bool image, Composite parent, Summary summ) { mixin(S_TRACE);
  1201. int len = image ? prop.looks.messageImageLen : prop.looks.messageLen;
  1202. auto r = new FixedWidthText(dwtData(prop.looks.messageFont(summ.legacy)), len, parent, SWT.BORDER, true);
  1203. auto d = r.widget.getDisplay();
  1204. auto back = new Color(d, new RGB(prop.var.etc.msgBackR, prop.var.etc.msgBackG, prop.var.etc.msgBackB));
  1205. auto fore = new Color(d, new RGB(prop.var.etc.msgForeR, prop.var.etc.msgForeG, prop.var.etc.msgForeB));
  1206. r.widget.setBackground(back);
  1207. r.widget.setForeground(fore);
  1208. r.widget.addDisposeListener(new DisposeText(back, fore));
  1209. return r;
  1210. }
  1211. private class PutC {
  1212. private void delegate(string) _insert;
  1213. private string _put;
  1214. this(void delegate(string) insert, string put) { mixin(S_TRACE);
  1215. _insert = insert;
  1216. _put = put;
  1217. }
  1218. void put() { mixin(S_TRACE);
  1219. _insert(_put);
  1220. }
  1221. }
  1222. private class PutColor {
  1223. private void delegate(dchar) _put;
  1224. private dchar _color;
  1225. this(void delegate(dchar) put, dchar color) { mixin(S_TRACE);
  1226. _put = put;
  1227. _color = color;
  1228. }
  1229. void put() { mixin(S_TRACE);
  1230. _put(_color);
  1231. }
  1232. }
  1233. private ToolBar createSCharBar(Commons comm, Composite parent,
  1234. void delegate(string) insert, void delegate(dchar) putColor, Props prop, Skin skin) { mixin(S_TRACE);
  1235. auto bar = new ToolBar(parent, SWT.FLAT);
  1236. comm.put(bar);
  1237. bar.addListener(SWT.Traverse, new class Listener {
  1238. override void handleEvent(Event e) {e.doit = true;}
  1239. });
  1240. bar.addListener(SWT.KeyDown, new class Listener {
  1241. override void handleEvent(Event e) {e.doit = true;}
  1242. });
  1243. foreach (c; [
  1244. 'W', 'R', 'B', 'G', 'Y'
  1245. ] ~ [
  1246. 'O', 'P', 'L', 'D' // CardWirth 1.50
  1247. ]) { mixin(S_TRACE);
  1248. string t;
  1249. final switch (c) {
  1250. case 'W': t = prop.msgs.colorW; break;
  1251. case 'R': t = prop.msgs.colorR; break;
  1252. case 'B': t = prop.msgs.colorB; break;
  1253. case 'G': t = prop.msgs.colorG; break;
  1254. case 'Y': t = prop.msgs.colorY; break;
  1255. case 'O': t = prop.msgs.colorO; break; // CardWirth 1.50
  1256. case 'P': t = prop.msgs.colorP; break; // CardWirth 1.50
  1257. case 'L': t = prop.msgs.colorL; break; // CardWirth 1.50
  1258. case 'D': t = prop.msgs.colorD; break; // CardWirth 1.50
  1259. }
  1260. createToolItem2(comm, bar, t, prop.images.color(c), &(new PutColor(putColor, c)).put, null);
  1261. }
  1262. new ToolItem(bar, SWT.SEPARATOR);
  1263. createToolItem2(comm, bar, prop.msgs.scRef, prop.images.scRef, &(new PutC(insert, "#I")).put, null);
  1264. createToolItem2(comm, bar, prop.msgs.scTalkerName(Talker.SELECTED), prop.images.scTalker(Talker.SELECTED),
  1265. &(new PutC(insert, "#M")).put, null);
  1266. createToolItem2(comm, bar, prop.msgs.scTalkerName(Talker.UNSELECTED), prop.images.scTalker(Talker.UNSELECTED),
  1267. &(new PutC(insert, "#U")).put, null);
  1268. createToolItem2(comm, bar, prop.msgs.scTalkerName(Talker.RANDOM), prop.images.scTalker(Talker.RANDOM),
  1269. &(new PutC(insert, "#R")).put, null);
  1270. createToolItem2(comm, bar, prop.msgs.scTalkerName(Talker.CARD), prop.images.scTalker(Talker.CARD),
  1271. &(new PutC(insert, "#C")).put, null);
  1272. createToolItem2(comm, bar, prop.msgs.scTeam, prop.images.scTeam, &(new PutC(insert, "#T")).put, null);
  1273. createToolItem2(comm, bar, prop.msgs.scYado, prop.images.scYado, &(new PutC(insert, "#Y")).put, null);
  1274. return bar;
  1275. }
  1276. private ToolBar createSkinSCharBar(Commons comm, Composite parent, void delegate(string) insert, Props prop, Skin skin) { mixin(S_TRACE);
  1277. auto bar = new ToolBar(parent, SWT.FLAT);
  1278. comm.put(bar);
  1279. bar.addListener(SWT.Traverse, new class Listener {
  1280. override void handleEvent(Event e) {e.doit = true;}
  1281. });
  1282. bar.addListener(SWT.KeyDown, new class Listener {
  1283. override void handleEvent(Event e) {e.doit = true;}
  1284. });
  1285. Image[] imgs;
  1286. foreach (spc; skin.spChars.keys) { mixin(S_TRACE);
  1287. auto img = new Image(Display.getCurrent(), spChar(skin, spc));
  1288. string name = toUTF8("#"d ~ spc);
  1289. auto scp = new PutC(insert, name);
  1290. createToolItem2(comm, bar, name, img, &scp.put, null);
  1291. imgs ~= img;
  1292. }
  1293. bar.addDisposeListener(new class DisposeListener {
  1294. private Image[] _imgs;
  1295. this() {_imgs = imgs;}
  1296. override void widgetDisposed(DisposeEvent e) { mixin(S_TRACE);
  1297. foreach (img; _imgs) { mixin(S_TRACE);
  1298. img.dispose();
  1299. }
  1300. }
  1301. });
  1302. return bar;
  1303. }
  1304. private Composite createFlagStepBar(Composite parent, void delegate(string) insert, Commons comm, Props prop) { mixin(S_TRACE);
  1305. auto bar = new Composite(parent, SWT.NONE);
  1306. bar.setLayout(zeroMarginGridLayout(2, true));
  1307. void create(out Combo list, out Button put, string puts, Image image, string lc) { mixin(S_TRACE);
  1308. auto comp = new Composite(bar, SWT.NONE);
  1309. comp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  1310. comp.setLayout(zeroMarginGridLayout(2, false));
  1311. list = new Combo(comp, SWT.READ_ONLY | SWT.DROP_DOWN | SWT.BORDER);
  1312. list.setVisibleItemCount(prop.var.etc.comboVisibleItemCount);
  1313. list.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  1314. put = new Button(comp, SWT.PUSH);
  1315. put.setToolTipText(puts);
  1316. put.setImage(image);
  1317. put.addSelectionListener(new class SelectionAdapter {
  1318. override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  1319. insert(lc ~ list.getText() ~ lc);
  1320. }
  1321. });
  1322. }
  1323. Combo flags, steps;
  1324. Button putFlag, putStep;
  1325. create(flags, putFlag, prop.msgs.addMsgRefFlag, prop.images.flag, "%");
  1326. create(steps, putStep, prop.msgs.addMsgRefStep, prop.images.step, "$");
  1327. void refList() { mixin(S_TRACE);
  1328. auto root = comm.summary.flagDirRoot;
  1329. auto fSel = flags.getText();
  1330. auto sSel = steps.getText();
  1331. flags.removeAll();
  1332. foreach (i, flag; root.allFlags) { mixin(S_TRACE);
  1333. auto p = flag.path;
  1334. flags.add(p);
  1335. if (0 == i || 0 == icmp(p, fSel)) flags.select(i);
  1336. }
  1337. steps.removeAll();
  1338. foreach (i, step; root.allSteps) { mixin(S_TRACE);
  1339. auto p = step.path;
  1340. steps.add(p);
  1341. if (0 == i || 0 == icmp(p, sSel)) steps.select(i);
  1342. }
  1343. flags.setEnabled(flags.getItemCount() > 0);
  1344. putFlag.setEnabled(flags.getEnabled());
  1345. steps.setEnabled(steps.getItemCount() > 0);
  1346. putStep.setEnabled(steps.getEnabled());
  1347. }
  1348. refList();
  1349. void refFlagAndStep(Flag[] flags, Step[] steps) { mixin(S_TRACE);
  1350. refList();
  1351. }
  1352. comm.refFlagAndStep.add(&refFlagAndStep);
  1353. comm.delFlagAndStep.add(&refFlagAndStep);
  1354. bar.addDisposeListener(new class DisposeListener {
  1355. override void widgetDisposed(DisposeEvent e) { mixin(S_TRACE);
  1356. comm.refFlagAndStep.remove(&refFlagAndStep);
  1357. comm.delFlagAndStep.remove(&refFlagAndStep);
  1358. }
  1359. });
  1360. return bar;
  1361. }
  1362. private void putColor(FixedWidthText text, dchar put) { mixin(S_TRACE);
  1363. auto sel = text.widget.getSelection();
  1364. auto old = toUTF32(text.getText());
  1365. auto newt = cwx.msgutils.putColor(old, put, sel.x, sel.y);
  1366. text.setText(toUTF8(newt));
  1367. int nSel = sel.y + (newt.length - old.length);
  1368. text.widget.setSelection(nSel);
  1369. }
  1370. class MsgPreviewWindow {
  1371. private MsgPreview _preview;
  1372. private Button _toggle;
  1373. private WSize _size;
  1374. private Shell _win;
  1375. private ControlListener _winL;
  1376. private int _parX, _parY;
  1377. private class Dispose : DisposeListener {
  1378. override void widgetDisposed(DisposeEvent e) { mixin(S_TRACE);
  1379. _win.getParent().removeControlListener(_winL);
  1380. saveWin();
  1381. }
  1382. }
  1383. private class PShellL : ControlAdapter {
  1384. override void controlMoved(ControlEvent e) { mixin(S_TRACE);
  1385. auto pb = _win.getParent().getBounds();
  1386. auto tb = _win.getBounds();
  1387. _win.setBounds(tb.x + pb.x - _parX, tb.y + pb.y - _parY, tb.width, tb.height);
  1388. _parX = pb.x;
  1389. _parY = pb.y;
  1390. }
  1391. }
  1392. private class ShellL : ShellAdapter {
  1393. override void shellClosed(ShellEvent e) { mixin(S_TRACE);
  1394. close();
  1395. e.doit = false;
  1396. }
  1397. }
  1398. this (Shell parent, Commons comm, Props prop, Summary summ, Button toggle, WSize size) { mixin(S_TRACE);
  1399. _size = size;
  1400. _toggle = toggle;
  1401. _winL = new PShellL;
  1402. parent.addControlListener(_winL);
  1403. _win = new Shell(parent, SWT.TITLE | SWT.RESIZE | SWT.TOOL | SWT.CLOSE);
  1404. _win.setText(prop.msgs.dlgTitMessagePreview);
  1405. auto cl = new CenterLayout(SWT.HORIZONTAL | SWT.VERTICAL, 0);
  1406. cl.fillHorizontal = true;
  1407. cl.fillVertical = true;
  1408. _win.setLayout(cl);
  1409. _win.addShellListener(new ShellL);
  1410. _win.addDisposeListener(new Dispose);
  1411. _preview = new MsgPreview(_win, comm, prop, summ);
  1412. }
  1413. private void saveWin() { mixin(S_TRACE);
  1414. auto winProps = _size;
  1415. winProps.width = _win.getSize().x;
  1416. winProps.height = _win.getSize().y;
  1417. winProps.x = _win.getBounds().x - _win.getParent().getBounds().x;
  1418. winProps.y = _win.getBounds().y - _win.getParent().getBounds().y;
  1419. }
  1420. bool isVisible() {return _win.isVisible();}
  1421. void open() { mixin(S_TRACE);
  1422. if (_win.isVisible()) return;
  1423. auto pb = _win.getParent().getBounds();
  1424. _parX = pb.x;
  1425. _parY = pb.y;
  1426. auto winProps = _size;
  1427. scope wp = _win.computeSize(SWT.DEFAULT, SWT.DEFAULT);
  1428. int width = winProps.width == SWT.DEFAULT ? wp.x : winProps.width;
  1429. int height = winProps.height == SWT.DEFAULT ? wp.y : winProps.height;
  1430. int x = winProps.x == SWT.DEFAULT ? pb.x + pb.width : winProps.x + pb.x;
  1431. int y = winProps.y == SWT.DEFAULT ? pb.y : winProps.y + pb.y;
  1432. intoDisplay(x, y, width, height);
  1433. _win.setBounds(x, y, width, height);
  1434. refresh();
  1435. _win.setVisible(true);
  1436. _toggle.setSelection(true);
  1437. }
  1438. void close() { mixin(S_TRACE);
  1439. if (!_win.isVisible()) return;
  1440. saveWin();
  1441. _win.setVisible(false);
  1442. _toggle.setSelection(false);
  1443. }
  1444. void text(Talker talker, string imgPath, string message) { mixin(S_TRACE);
  1445. _preview.text(talker, imgPath, message);
  1446. }
  1447. private void refresh() { mixin(S_TRACE);
  1448. _preview.refresh();
  1449. }
  1450. }
  1451. enum SPChar {
  1452. M = 0, /// ???
  1453. U = 1, /// ???
  1454. R = 2, /// ????
  1455. C = 3, /// ???
  1456. I = 4, /// ??
  1457. T = 5, /// ???
  1458. Y = 6 /// ?
  1459. }
  1460. immutable SPCHAR_ALL = [
  1461. SPChar.M,
  1462. SPChar.U,
  1463. SPChar.R,
  1464. SPChar.C,
  1465. SPChar.I,
  1466. SPChar.T,
  1467. SPChar.Y,
  1468. ];
  1469. immutable SPCHAR_TEXT = [
  1470. SPChar.M,
  1471. SPChar.U,
  1472. SPChar.R,
  1473. SPChar.T,
  1474. SPChar.Y,
  1475. ];
  1476. private immutable C_TBL = [
  1477. 'M',
  1478. 'U',
  1479. 'R',
  1480. 'C',
  1481. 'I',
  1482. 'T',
  1483. 'Y',
  1484. ];
  1485. class PreviewValues : Composite {
  1486. void delegate()[] modEvent;
  1487. private static class FlagData {
  1488. Flag flag;
  1489. bool onOff;
  1490. }
  1491. private static class StepData {
  1492. Step step;
  1493. int select;
  1494. }
  1495. private Commons _comm;
  1496. private Props _prop;
  1497. private Summary _summ;
  1498. private bool _isMessage;
  1499. private const(SPChar)[] _targetChars;
  1500. private Table _values;
  1501. private int[SPChar] _indexTable;
  1502. private UndoManager _undo;
  1503. private bool _changedText = false;
  1504. private class UndoPV : Undo {
  1505. private string[char] _names;
  1506. private bool[string] _flags;
  1507. private int[string] _steps;
  1508. this () { mixin(S_TRACE);
  1509. getValues2(_names, _flags, _steps);
  1510. }
  1511. private void impl() { mixin(S_TRACE);
  1512. string[char] names;
  1513. bool[string] flags;
  1514. int[string] steps;
  1515. getValues2(names, flags, steps);
  1516. setValues2(_names, _flags, _steps);
  1517. _names = names;
  1518. _flags = flags;
  1519. _steps = steps;
  1520. raiseModEvent();
  1521. }
  1522. override void undo() { impl(); }
  1523. override void redo() { impl(); }
  1524. override void dispose() { mixin(S_TRACE);
  1525. // Nothing
  1526. }
  1527. }
  1528. private void store() { mixin(S_TRACE);
  1529. _undo ~= new UndoPV;
  1530. }
  1531. private void refUndoMax() { mixin(S_TRACE);
  1532. _undo.max = _prop.var.etc.undoMaxEtc;
  1533. }
  1534. private class Dispose : DisposeListener {
  1535. override void widgetDisposed(DisposeEvent e) { mixin(S_TRACE);
  1536. _comm.refUndoMax.remove(&refUndoMax);
  1537. _comm.refFlagAndStep.remove(&refFlagAndStep);
  1538. _comm.delFlagAndStep.remove(&refFlagAndStep);
  1539. if (SPChar.M in _indexTable) _prop.var.etc.messageVarSelected = _values.getItem(_indexTable[SPChar.M]).getText(1);
  1540. if (SPChar.U in _indexTable) _prop.var.etc.messageVarUnselected = _values.getItem(_indexTable[SPChar.U]).getText(1);
  1541. if (SPChar.R in _indexTable) _prop.var.etc.messageVarRandom = _values.getItem(_indexTable[SPChar.R]).getText(1);
  1542. if (SPChar.C in _indexTable) _prop.var.etc.messageVarCard = _values.getItem(_indexTable[SPChar.C]).getText(1);
  1543. if (SPChar.I in _indexTable) _prop.var.etc.messageVarRef = _values.getItem(_indexTable[SPChar.I]).getText(1);
  1544. if (SPChar.T in _indexTable) _prop.var.etc.messageVarTeam = _values.getItem(_indexTable[SPChar.T]).getText(1);
  1545. if (SPChar.Y in _indexTable) _prop.var.etc.messageVarYado = _values.getItem(_indexTable[SPChar.Y]).getText(1);
  1546. if (_isMessage) { mixin(S_TRACE);
  1547. _prop.var.etc.messageVarKindColumn = _values.getColumn(0).getWidth();
  1548. _prop.var.etc.messageVarValueColumn = _values.getColumn(1).getWidth();
  1549. } else { mixin(S_TRACE);
  1550. _prop.var.etc.textVarKindColumn = _values.getColumn(0).getWidth();
  1551. _prop.var.etc.textVarValueColumn = _values.getColumn(1).getWidth();
  1552. }
  1553. _comm.refPreviewValues.call();
  1554. }
  1555. }
  1556. private class Mod : ModifyListener {
  1557. private TableItem _itm;
  1558. this (TableItem itm) { mixin(S_TRACE);
  1559. _itm = itm;
  1560. }
  1561. override void modifyText(ModifyEvent e) { mixin(S_TRACE);
  1562. if (!_changedText) { mixin(S_TRACE);
  1563. store();
  1564. _changedText = true;
  1565. }
  1566. string text = ctrlText(cast(Control) e.widget);
  1567. _itm.setText(1, text);
  1568. raiseModEvent();
  1569. }
  1570. }
  1571. private void refreshFlags() { mixin(S_TRACE);
  1572. _values.setRedraw(false);
  1573. scope (exit) _values.setRedraw(true);
  1574. int topIndex = _values.getTopIndex();
  1575. scope (exit) {
  1576. if (_values.getItemCount() <= topIndex) {
  1577. topIndex = _values.getItemCount() - 1;
  1578. }
  1579. _values.setTopIndex(topIndex);
  1580. }
  1581. int[string] pvs;
  1582. string selPath = null;
  1583. if (_targetChars.length < _values.getItemCount()) { mixin(S_TRACE);
  1584. foreach (i; _targetChars.length .. _values.getItemCount()) { mixin(S_TRACE);
  1585. auto itm = _values.getItem(i);
  1586. string key = .toLower(itm.getText(0));
  1587. auto o = itm.getData();
  1588. auto f = cast(FlagData) o;
  1589. if (f) pvs[key] = f.onOff ? 1 : 0;
  1590. auto s = cast(StepData) o;
  1591. if (s) pvs[key] = s.select;
  1592. if (i == _values.getSelectionIndex()) { mixin(S_TRACE);
  1593. selPath = key;
  1594. }
  1595. }
  1596. _values.remove(_targetChars.length, _values.getItemCount() - 1);
  1597. }
  1598. if (_summ) { mixin(S_TRACE);
  1599. foreach (f; _summ.flagDirRoot.allFlags) { mixin(S_TRACE);
  1600. auto itm = new TableItem(_values, SWT.NONE);
  1601. auto path = f.path;
  1602. itm.setImage(0, _prop.images.flag);
  1603. itm.setText(0, path);
  1604. itm.setText(1, f.onOff ? f.on : f.off);
  1605. auto d = new FlagData;
  1606. itm.setData(d);
  1607. d.flag = f;
  1608. d.onOff = f.onOff;
  1609. string lpath = .toLower(path);
  1610. auto p = lpath in pvs;
  1611. if (p) { mixin(S_TRACE);
  1612. if (*p == 1) { mixin(S_TRACE);
  1613. itm.setText(1, f.on);
  1614. d.onOff = true;
  1615. } else if (*p == 0) { mixin(S_TRACE);
  1616. itm.setText(1, f.off);
  1617. d.onOff = false;
  1618. }
  1619. }
  1620. if (selPath && selPath == lpath) { mixin(S_TRACE);
  1621. _values.select(_values.getItemCount() - 1);
  1622. }
  1623. }
  1624. foreach (f; _summ.flagDirRoot.allSteps) { mixin(S_TRACE);
  1625. auto itm = new TableItem(_values, SWT.NONE);
  1626. auto path = f.path;
  1627. itm.setImage(0, _prop.images.step);
  1628. itm.setText(0, path);
  1629. itm.setText(1, f.values[f.select]);
  1630. auto d = new StepData;
  1631. itm.setData(d);
  1632. d.step = f;
  1633. d.select = f.select;
  1634. string lpath = .toLower(path);
  1635. auto p = lpath in pvs;
  1636. if (p) { mixin(S_TRACE);
  1637. if (0 <= *p && *p < f.values.length) { mixin(S_TRACE);
  1638. itm.setText(1, f.values[*p]);
  1639. d.select = *p;
  1640. }
  1641. }
  1642. if (selPath && selPath == lpath) { mixin(S_TRACE);
  1643. _values.select(_values.getItemCount() - 1);
  1644. }
  1645. }
  1646. }
  1647. }
  1648. private void refFlagAndStep(Flag[] flags, Step[] steps) { mixin(S_TRACE);
  1649. _undo.reset();
  1650. refreshFlags();
  1651. raiseModEvent();
  1652. }
  1653. private Control createEditor(TableItem itm, int editC) { mixin(S_TRACE);
  1654. _changedText = false;
  1655. auto fd = cast(FlagData) itm.getData();
  1656. if (fd) { mixin(S_TRACE);
  1657. auto text = createComboEditor!Combo(_comm, _prop, itm.getParent(), [fd.flag.on, fd.flag.off], itm.getText(1));
  1658. text.addModifyListener(new Mod(itm));
  1659. return text;
  1660. }
  1661. auto sd = cast(StepData) itm.getData();
  1662. if (sd) { mixin(S_TRACE);
  1663. auto text = createComboEditor!Combo(_comm, _prop, itm.getParent(), sd.step.values, itm.getText(1));
  1664. text.addModifyListener(new Mod(itm));
  1665. return text;
  1666. }
  1667. auto combo = createTextEditor(_comm, _prop, itm.getParent(), itm.getText(1));
  1668. combo.addModifyListener(new Mod(itm));
  1669. return combo;
  1670. }
  1671. private static string ctrlText(Control ctrl) { mixin(S_TRACE);
  1672. auto text = cast(Text) ctrl;
  1673. if (text) return text.getText();
  1674. auto combo = cast(Combo) ctrl;
  1675. if (combo) return combo.getText();
  1676. assert (0);
  1677. }
  1678. private void editEnd(TableItem itm, int column, Control ctrl) { mixin(S_TRACE);
  1679. auto old = itm.getText(column);
  1680. auto text = cast(Text) ctrl;
  1681. if (text) itm.setText(column, text.getText());
  1682. auto combo = cast(Combo) ctrl;
  1683. if (combo) { mixin(S_TRACE);
  1684. itm.setText(column, combo.getText());
  1685. auto fd = cast(FlagData) itm.getData();
  1686. if (fd) fd.onOff = combo.getSelectionIndex() == 0;
  1687. auto sd = cast(StepData) itm.getData();
  1688. if (sd) sd.select = combo.getSelectionIndex();
  1689. }
  1690. if (old != itm.getText()) raiseModEvent();
  1691. }
  1692. private void raiseModEvent() { mixin(S_TRACE);
  1693. foreach (dlg; modEvent) dlg();
  1694. _comm.refreshToolBar();
  1695. }
  1696. void resetValues() { mixin(S_TRACE);
  1697. return resetValues(_values.getSelectionIndices());
  1698. }
  1699. void resetValuesAll() { mixin(S_TRACE);
  1700. return resetValues(std.range.iota(0, _values.getItemCount()).array());
  1701. }
  1702. void resetValues(in int[] indices) { mixin(S_TRACE);
  1703. bool[int] set;
  1704. foreach (i; indices) set[i] = true;
  1705. store();
  1706. size_t i = 0;
  1707. foreach (c; _targetChars) { mixin(S_TRACE);
  1708. if (i in set) { mixin(S_TRACE);
  1709. auto itm = _values.getItem(_indexTable[cast(SPChar)c]);
  1710. final switch (cast(SPChar)c) {
  1711. case SPChar.M:
  1712. itm.setText(1, _prop.var.etc.messageVarSelected.INIT);
  1713. break;
  1714. case SPChar.U:
  1715. itm.setText(1, _prop.var.etc.messageVarUnselected.INIT);
  1716. break;
  1717. case SPChar.R:
  1718. itm.setText(1, _prop.var.etc.messageVarRandom.INIT);
  1719. break;
  1720. case SPChar.C:
  1721. itm.setText(1, _prop.var.etc.messageVarCard.INIT);
  1722. break;
  1723. case SPChar.I:
  1724. itm.setText(1, _prop.var.etc.messageVarRef.INIT);
  1725. break;
  1726. case SPChar.T:
  1727. itm.setText(1, _prop.var.etc.messageVarTeam.INIT);
  1728. break;
  1729. case SPChar.Y:
  1730. itm.setText(1, _prop.var.etc.messageVarYado.INIT);
  1731. break;
  1732. }
  1733. }
  1734. i++;
  1735. }
  1736. if (_summ) { mixin(S_TRACE);
  1737. foreach (f; _summ.flagDirRoot.allFlags) { mixin(S_TRACE);
  1738. if (i in set) { mixin(S_TRACE);
  1739. auto itm = _values.getItem(i);
  1740. itm.setText(1, f.onOff ? f.on : f.off);
  1741. auto data = cast(FlagData) itm.getData();
  1742. data.onOff = f.onOff;
  1743. }
  1744. i++;
  1745. }
  1746. foreach (f; _summ.flagDirRoot.allSteps) { mixin(S_TRACE);
  1747. if (i in set) { mixin(S_TRACE);
  1748. auto itm = _values.getItem(i);
  1749. itm.setText(1, f.values[f.select]);
  1750. auto data = cast(StepData) itm.getData();
  1751. data.select = f.select;
  1752. }
  1753. i++;
  1754. }
  1755. }
  1756. raiseModEvent();
  1757. }
  1758. bool isInitialValues() { mixin(S_TRACE);
  1759. return isInitialValues(_values.getSelectionIndices());
  1760. }
  1761. bool isInitialValuesAll() { mixin(S_TRACE);
  1762. return isInitialValues(std.range.iota(0, _values.getItemCount()).array());
  1763. }
  1764. bool isInitialValues(in int[] indices) { mixin(S_TRACE);
  1765. bool[int] set;
  1766. foreach (i; indices) set[i] = true;
  1767. size_t i = 0;
  1768. foreach (c; _targetChars) { mixin(S_TRACE);
  1769. if (i in set) { mixin(S_TRACE);
  1770. auto itm = _values.getItem(_indexTable[cast(SPChar)c]);
  1771. final switch (cast(SPChar)c) {
  1772. case SPChar.M:
  1773. if (itm.getText(1) != _prop.var.etc.messageVarSelected.INIT) return false;
  1774. break;
  1775. case SPChar.U:
  1776. if (itm.getText(1) != _prop.var.etc.messageVarUnselected.INIT) return false;
  1777. break;
  1778. case SPChar.R:
  1779. if (itm.getText(1) != _prop.var.etc.messageVarRandom.INIT) return false;
  1780. break;
  1781. case SPChar.C:
  1782. if (itm.getText(1) != _prop.var.etc.messageVarCard.INIT) return false;
  1783. break;
  1784. case SPChar.I:
  1785. if (itm.getText(1) != _prop.var.etc.messageVarRef.INIT) return false;
  1786. break;
  1787. case SPChar.T:
  1788. if (itm.getText(1) != _prop.var.etc.messageVarTeam.INIT) return false;
  1789. break;
  1790. case SPChar.Y:
  1791. if (itm.getText(1) != _prop.var.etc.messageVarYado.INIT) return false;
  1792. break;
  1793. }
  1794. }
  1795. i++;
  1796. }
  1797. if (_summ) { mixin(S_TRACE);
  1798. foreach (f; _summ.flagDirRoot.allFlags) { mixin(S_TRACE);
  1799. if (i in set) { mixin(S_TRACE);
  1800. auto itm = _values.getItem(i);
  1801. auto data = cast(FlagData) itm.getData();
  1802. if (data.onOff != f.onOff) return false;
  1803. }
  1804. i++;
  1805. }
  1806. foreach (f; _summ.flagDirRoot.allSteps) { mixin(S_TRACE);
  1807. if (i in set) { mixin(S_TRACE);
  1808. auto itm = _values.getItem(i);
  1809. auto data = cast(StepData) itm.getData();
  1810. if (data.select != f.select) return false;
  1811. }
  1812. i++;
  1813. }
  1814. }
  1815. return true;
  1816. }
  1817. class ValuesTCPD : TCPD {
  1818. void cut(SelectionEvent e) { assert (0); };
  1819. void copy(SelectionEvent e) { mixin(S_TRACE);
  1820. auto indices = _values.getSelectionIndices().sort;
  1821. if (!indices.length) return;
  1822. string text;
  1823. foreach (sel; indices[0] .. indices[$ - 1] + 1) { mixin(S_TRACE);
  1824. auto itm = _values.getItem(sel);
  1825. auto fd = cast(FlagData) itm.getData();
  1826. auto sd = cast(StepData) itm.getData();
  1827. if (fd) { mixin(S_TRACE);
  1828. text ~= to!string(fd.onOff);
  1829. } else if (sd) { mixin(S_TRACE);
  1830. text ~= to!string(sd.select);
  1831. } else { mixin(S_TRACE);
  1832. text ~= itm.getText(1);
  1833. }
  1834. text ~= std.ascii.newline;
  1835. }
  1836. _comm.clipboard.setContents([new ArrayWrapperString(text)], [TextTransfer.getInstance()]);
  1837. _comm.refreshToolBar();
  1838. }
  1839. void paste(SelectionEvent e) { mixin(S_TRACE);
  1840. auto a = cast(ArrayWrapperString) _comm.clipboard.getContents(TextTransfer.getInstance());
  1841. if (!a) return;
  1842. auto indices = _values.getSelectionIndices().sort;
  1843. if (!indices.length) return;
  1844. int i = indices[0];
  1845. auto linesu = a.array.splitLines();
  1846. if (!linesu.length) return;
  1847. store();
  1848. auto lines = assumeUnique(linesu);
  1849. int[] sels;
  1850. foreach (line; lines) { mixin(S_TRACE);
  1851. if (_values.getItemCount() <= i) break;
  1852. auto itm = _values.getItem(i);
  1853. auto fd = cast(FlagData) itm.getData();
  1854. auto sd = cast(StepData) itm.getData();
  1855. try { mixin(S_TRACE);
  1856. if (fd) { mixin(S_TRACE);
  1857. fd.onOff = to!bool(line);
  1858. itm.setText(1, fd.onOff ? fd.flag.on : fd.flag.off);
  1859. } else if (sd) { mixin(S_TRACE);
  1860. auto value = to!int(line);
  1861. if (0 <= value && value < sd.step.values.length) { mixin(S_TRACE);
  1862. sd.select = value;
  1863. itm.setText(1, sd.step.values[sd.select]);
  1864. }
  1865. } else { mixin(S_TRACE);
  1866. itm.setText(1, line);
  1867. }
  1868. } catch (ConvException e) {
  1869. debugln(e);
  1870. }
  1871. sels ~= i;
  1872. i++;
  1873. }
  1874. _values.deselectAll();
  1875. _values.select(sels);
  1876. _values.showSelection();
  1877. raiseModEvent();
  1878. }
  1879. void del(SelectionEvent e) { assert (0); };
  1880. void clone(SelectionEvent e) { assert (0); };
  1881. bool canDoTCPD() { mixin(S_TRACE);
  1882. return _values.isFocusControl();
  1883. }
  1884. bool canDoT() { return false; }
  1885. bool canDoC() { return -1 != _values.getSelectionIndex(); }
  1886. bool canDoP() { return -1 != _values.getSelectionIndex() && CBisText(_comm.clipboard); }
  1887. bool canDoD() { return false; }
  1888. bool canDoClone() { return false; }
  1889. }
  1890. this (Composite parent, Commons comm, Props prop, Summary summ, bool message) { mixin(S_TRACE);
  1891. super (parent, SWT.NONE);
  1892. _undo = new UndoManager(prop.var.etc.undoMaxEtc);
  1893. _comm = comm;
  1894. _prop = prop;
  1895. _summ = summ;
  1896. _isMessage = message;
  1897. _targetChars = message ? SPCHAR_ALL : SPCHAR_TEXT;
  1898. this.setLayout(zeroGridLayout(1, true));
  1899. _values = new Table(this, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI);
  1900. auto vgd = new GridData(GridData.FILL_BOTH);
  1901. vgd.heightHint = _prop.var.etc.messageVarTableHeight;
  1902. _values.setLayoutData(vgd);
  1903. _values.addDisposeListener(new Dispose);
  1904. _values.setHeaderVisible(true);
  1905. auto menu = new Menu(_values);
  1906. createMenuItem(comm, menu, MenuID.Undo, {_undo.undo();}, &_undo.canUndo);
  1907. createMenuItem(comm, menu, MenuID.Redo, {_undo.redo();}, &_undo.canRedo);
  1908. new MenuItem(menu, SWT.SEPARATOR);
  1909. createMenuItem(comm, menu, MenuID.ResetPreviewValues, &resetValues, () => !isInitialValues());
  1910. createMenuItem(comm, menu, MenuID.ResetPreviewValuesAll, &resetValuesAll, () => !isInitialValuesAll());
  1911. new MenuItem(menu, SWT.SEPARATOR);
  1912. appendMenuTCPD(comm, menu, new ValuesTCPD, false, true, true, false, false);
  1913. new MenuItem(menu, SWT.SEPARATOR);
  1914. createMenuItem(comm, menu, MenuID.SelectAll, &_values.selectAll, () => _values.getSelectionCount() < _values.getItemCount());
  1915. _values.setMenu(menu);
  1916. auto kindCol = new TableColumn(_values, SWT.NONE);
  1917. kindCol.setText(_prop.msgs.messageVarKindColumn);
  1918. auto valueCol = new TableColumn(_values, SWT.NONE);
  1919. valueCol.setText(_prop.msgs.messageVarValueColumn);
  1920. if (_isMessage) { mixin(S_TRACE);
  1921. kindCol.setWidth(_prop.var.etc.messageVarKindColumn);
  1922. valueCol.setWidth(_prop.var.etc.messageVarValueColumn);
  1923. } else { mixin(S_TRACE);
  1924. kindCol.setWidth(_prop.var.etc.textVarKindColumn);
  1925. valueCol.setWidth(_prop.var.etc.textVarValueColumn);
  1926. }
  1927. foreach (i; _targetChars) { mixin(S_TRACE);
  1928. _indexTable[cast(SPChar)i] = _values.getItemCount();
  1929. auto itm = new TableItem(_values, SWT.NONE);
  1930. final switch (cast(SPChar)i) {
  1931. case SPChar.M:
  1932. itm.setImage(0, _prop.images.scTalker(Talker.SELECTED));
  1933. itm.setText(0, _prop.msgs.scTalkerName(Talker.SELECTED));
  1934. itm.setText(1, _prop.var.etc.messageVarSelected);
  1935. break;
  1936. case SPChar.U:
  1937. itm.setImage(0, _prop.images.scTalker(Talker.UNSELECTED));
  1938. itm.setText(0, _prop.msgs.scTalkerName(Talker.UNSELECTED));
  1939. itm.setText(1, _prop.var.etc.messageVarUnselected);
  1940. break;
  1941. case SPChar.R:
  1942. itm.setImage(0, _prop.images.scTalker(Talker.RANDOM));
  1943. itm.setText(0, _prop.msgs.scTalkerName(Talker.RANDOM));
  1944. itm.setText(1, _prop.var.etc.messageVarRandom);
  1945. break;
  1946. case SPChar.C:
  1947. itm.setImage(0, _prop.images.scTalker(Talker.CARD));
  1948. itm.setText(0, _prop.msgs.scTalkerName(Talker.CARD));
  1949. itm.setText(1, _prop.var.etc.messageVarCard);
  1950. break;
  1951. case SPChar.I:
  1952. itm.setImage(0, _prop.images.scRef);
  1953. itm.setText(0, _prop.msgs.scRef);
  1954. itm.setText(1, _prop.var.etc.messageVarRef);
  1955. break;
  1956. case SPChar.T:
  1957. itm.setImage(0, _prop.images.scTeam);
  1958. itm.setText(0, _prop.msgs.scTeam);
  1959. itm.setText(1, _prop.var.etc.messageVarTeam);
  1960. break;
  1961. case SPChar.Y:
  1962. itm.setImage(0, _prop.images.scYado);
  1963. itm.setText(0, _prop.msgs.scYado);
  1964. itm.setText(1, _prop.var.etc.messageVarYado);
  1965. break;
  1966. }
  1967. }
  1968. refreshFlags();
  1969. _comm.refUndoMax.add(&refUndoMax);
  1970. _comm.refFlagAndStep.add(&refFlagAndStep);
  1971. _comm.delFlagAndStep.add(&refFlagAndStep);
  1972. new TableTCEdit(_comm, _values, 1, &createEditor, &editEnd, null);
  1973. }
  1974. void getValues(out string[char] names, out string[string] flags, out string[string] steps) { mixin(S_TRACE);
  1975. foreach (i; _targetChars) { mixin(S_TRACE);
  1976. names[C_TBL[cast(SPChar)i]] = _values.getItem(_indexTable[cast(SPChar)i]).getText(1);
  1977. }
  1978. foreach (i; _targetChars.length .. _values.getItemCount()) { mixin(S_TRACE);
  1979. auto itm = _values.getItem(i);
  1980. if (cast(FlagData) itm.getData()) { mixin(S_TRACE);
  1981. flags[itm.getText(0)] = itm.getText(1);
  1982. } else { mixin(S_TRACE);
  1983. assert (cast(StepData) itm.getData());
  1984. steps[itm.getText(0)] = itm.getText(1);
  1985. }
  1986. }
  1987. }
  1988. private void getValues2(out string[char] names, out bool[string] flags, out int[string] steps) { mixin(S_TRACE);
  1989. foreach (i; _targetChars) { mixin(S_TRACE);
  1990. names[C_TBL[cast(SPChar)i]] = _values.getItem(_indexTable[cast(SPChar)i]).getText(1);
  1991. }
  1992. foreach (i; _targetChars.length .. _values.getItemCount()) { mixin(S_TRACE);
  1993. auto itm = _values.getItem(i);
  1994. auto fd = cast(FlagData) itm.getData();
  1995. if (fd) { mixin(S_TRACE);
  1996. flags[itm.getText(0)] = fd.onOff;
  1997. } else { mixin(S_TRACE);
  1998. auto sd = cast(StepData) itm.getData();
  1999. assert (sd !is null);
  2000. steps[itm.getText(0)] = sd.select;
  2001. }
  2002. }
  2003. }
  2004. private void setValues2(in string[char] names, in bool[string] flags, in int[string] steps) { mixin(S_TRACE);
  2005. foreach (i; _targetChars) { mixin(S_TRACE);
  2006. _values.getItem(_indexTable[cast(SPChar)i]).setText(1, names[C_TBL[cast(SPChar)i]]);
  2007. }
  2008. foreach (i; _targetChars.length .. _values.getItemCount()) { mixin(S_TRACE);
  2009. auto itm = _values.getItem(i);
  2010. auto fd = cast(FlagData) itm.getData();
  2011. if (fd) { mixin(S_TRACE);
  2012. auto p = itm.getText(0) in flags;
  2013. if (p) { mixin(S_TRACE);
  2014. fd.onOff = *p;
  2015. itm.setText(1, fd.onOff ? fd.flag.on : fd.flag.off);
  2016. }
  2017. } else { mixin(S_TRACE);
  2018. auto sd = cast(StepData) itm.getData();
  2019. assert (sd !is null);
  2020. auto p = itm.getText(0) in steps;
  2021. if (p && 0 <= *p && *p < sd.step.values.length) { mixin(S_TRACE);
  2022. sd.select = *p;
  2023. itm.setText(1, sd.step.values[sd.select]);
  2024. }
  2025. }
  2026. }
  2027. }
  2028. @property
  2029. bool focusInValues() { mixin(S_TRACE);
  2030. return _values.isFocusControl();
  2031. }
  2032. bool undo() { return _undo.undo(); }
  2033. bool redo() { return _undo.redo(); }
  2034. }
  2035. void getPreviewValues(in Props prop, in Summary summ, in SPChar[] targetChars,
  2036. out string[char] names, out string[string] flags, out string[string] steps) { mixin(S_TRACE);
  2037. foreach (c; targetChars) { mixin(S_TRACE);
  2038. final switch (c) {
  2039. case SPChar.M:
  2040. names[C_TBL[c]] = prop.var.etc.messageVarSelected;
  2041. break;
  2042. case SPChar.U:
  2043. names[C_TBL[c]] = prop.var.etc.messageVarUnselected;
  2044. break;
  2045. case SPChar.R:
  2046. names[C_TBL[c]] = prop.var.etc.messageVarRandom;
  2047. break;
  2048. case SPChar.C:
  2049. names[C_TBL[c]] = prop.var.etc.messageVarCard;
  2050. break;
  2051. case SPChar.I:
  2052. names[C_TBL[c]] = prop.var.etc.messageVarRef;
  2053. break;
  2054. case SPChar.T:
  2055. names[C_TBL[c]] = prop.var.etc.messageVarTeam;
  2056. break;
  2057. case SPChar.Y:
  2058. names[C_TBL[c]] = prop.var.etc.messageVarYado;
  2059. break;
  2060. }
  2061. }
  2062. if (summ) { mixin(S_TRACE);
  2063. foreach (f; summ.flagDirRoot.allFlags) { mixin(S_TRACE);
  2064. flags[f.path] = f.onOff ? f.on : f.off;
  2065. }
  2066. foreach (f; summ.flagDirRoot.allSteps) { mixin(S_TRACE);
  2067. steps[f.path] = f.value;
  2068. }
  2069. }
  2070. }
  2071. class MsgPreview : Composite {
  2072. private Commons _comm;
  2073. private Props _prop;
  2074. private Summary _summ;
  2075. private Canvas _canvas;
  2076. private Image _img = null;
  2077. private PreviewValues _values;
  2078. private Talker _talker = Talker.NARRATION;
  2079. private string _imgPath = "";
  2080. private string _message = "";
  2081. private class Paint : PaintListener {
  2082. override void paintControl(PaintEvent e) { mixin(S_TRACE);
  2083. auto b = _canvas.getBounds();
  2084. auto rect = _prop.looks.messageBounds;
  2085. e.gc.drawImage(_img, (b.width - rect.width) / 2, (b.height - rect.height) / 2);
  2086. }
  2087. }
  2088. private class Dispose : DisposeListener {
  2089. override void widgetDisposed(DisposeEvent e) { mixin(S_TRACE);
  2090. if (_img) _img.dispose();
  2091. _comm.refSkin.remove(&refresh);
  2092. }
  2093. }
  2094. this (Composite parent, Commons comm, Props prop, Summary summ) { mixin(S_TRACE);
  2095. super (parent, SWT.NONE);
  2096. _comm = comm;
  2097. _prop = prop;
  2098. _summ = summ;
  2099. this.setLayout(zeroGridLayout(1, true));
  2100. _canvas = new Canvas(this, SWT.DOUBLE_BUFFERED);
  2101. auto cgd = new GridData(GridData.FILL_HORIZONTAL);
  2102. auto rect = _prop.looks.messageBounds;
  2103. cgd.widthHint = rect.width;
  2104. cgd.heightHint = rect.height;
  2105. _canvas.setLayoutData(cgd);
  2106. _canvas.addPaintListener(new Paint);
  2107. _canvas.addDisposeListener(new Dispose);
  2108. _values = new PreviewValues(this, comm, prop, summ, true);
  2109. auto vgd = new GridData(GridData.FILL_BOTH);
  2110. vgd.heightHint = _prop.var.etc.messageVarTableHeight;
  2111. _values.setLayoutData(vgd);
  2112. _values.modEvent ~= &refresh;
  2113. _comm.refSkin.add(&refresh);
  2114. }
  2115. void text(Talker talker, string imgPath, string message) { mixin(S_TRACE);
  2116. if (_img && talker is _talker && imgPath == _imgPath && message == _message) { mixin(S_TRACE);
  2117. return;
  2118. }
  2119. _talker = talker;
  2120. _imgPath = imgPath;
  2121. _message = message;
  2122. if (isVisible()) refresh();
  2123. }
  2124. private void refresh() { mixin(S_TRACE);
  2125. auto d = _canvas.getDisplay();
  2126. if (_img) { mixin(S_TRACE);
  2127. _img.dispose();
  2128. }
  2129. ImageData tImg = null;
  2130. final switch (_talker) {
  2131. case Talker.NARRATION:
  2132. tImg = null;
  2133. break;
  2134. case Talker.SELECTED:
  2135. case Talker.UNSELECTED:
  2136. case Talker.RANDOM:
  2137. case Talker.VALUED:
  2138. tImg = _prop.images.talker(_talker).getImageData();
  2139. break;
  2140. case Talker.IMAGE:
  2141. tImg = loadImage(_comm.skin.findImagePath(_imgPath, _summ.scenarioPath), true);
  2142. break;
  2143. case Talker.CARD:
  2144. auto cRect = _prop.looks.cardSize;
  2145. tImg = menuCard(_comm.skin).scaledTo(cRect.width, cRect.height);
  2146. break;
  2147. }
  2148. string[char] names;
  2149. string[string] flags, steps;
  2150. _values.getValues(names, flags, steps);
  2151. _img = new Image(d, previewMessage(_comm, _prop, _summ.scenarioPath, tImg, _message, [], names, flags, steps));
  2152. _canvas.redraw();
  2153. }
  2154. @property
  2155. bool focusInValues() { mixin(S_TRACE);
  2156. return _values.focusInValues;
  2157. }
  2158. bool undo() { return _values.undo(); }
  2159. bool redo() { return _values.redo(); }
  2160. }
  2161. /// ?????????????????
  2162. ImageData previewMessage(Commons comm, Props prop, string sPath, ImageData talker, string message, in string[] sel, in string[char] names, in string[string] flags, in string[string] steps) { mixin(S_TRACE);
  2163. auto d = Display.getCurrent();
  2164. version (Windows) {
  2165. bool legacy = comm.skin.legacy;
  2166. } else { mixin(S_TRACE);
  2167. bool legacy = false;
  2168. }
  2169. auto rect = prop.looks.messageBounds;
  2170. auto bh = prop.looks.messageButtonHeight;
  2171. auto canvas = new Image(d, rect.width, rect.height + bh * sel.length);
  2172. scope (exit) canvas.dispose();
  2173. auto gc = new GC(canvas);
  2174. scope (exit) gc.dispose();
  2175. int alpha;
  2176. // ?????
  2177. auto back = new Color(d, dwtData(prop.var.etc.messageBackColor, alpha));
  2178. scope (exit) back.dispose();
  2179. gc.setBackground(back);
  2180. gc.fillRectangle(3, 3, rect.width - 6, rect.height - 6);
  2181. foreach (i; 0 .. sel.length) { mixin(S_TRACE);
  2182. gc.fillRectangle(3, rect.height + 3 + bh * i, rect.width - 6, bh - 6);
  2183. }
  2184. // ?????
  2185. if (talker) { mixin(S_TRACE);
  2186. auto tImg = new Image(d, talker);
  2187. scope (exit) tImg.dispose();
  2188. auto tp = prop.looks.messageTalkerPos;
  2189. auto cs = prop.looks.cardSize;
  2190. int tpy = tp.y + (cast(int) cs.height - cast(int) talker.height) / 2;
  2191. gc.drawImage(tImg, tp.x, tpy);
  2192. }
  2193. // ??????????
  2194. // ????
  2195. if (.contains(message, '\r')) { mixin(S_TRACE);
  2196. message = message.splitLines().join("\n");
  2197. }
  2198. // ???????????????
  2199. string[size_t] rFonts;
  2200. char[size_t] rColors;
  2201. string fValue(string path) { mixin(S_TRACE);
  2202. foreach (f, v; flags) { mixin(S_TRACE);
  2203. if (0 == icmp(f, path)) { mixin(S_TRACE);
  2204. return v;
  2205. }
  2206. }
  2207. return "%" ~ path ~ "%";
  2208. }
  2209. string sValue(string path) { mixin(S_TRACE);
  2210. foreach (f, v; steps) { mixin(S_TRACE);
  2211. if (0 == icmp(f, path)) { mixin(S_TRACE);
  2212. return v;
  2213. }
  2214. }
  2215. return "$" ~ path ~ "$";
  2216. }
  2217. version (Windows) {
  2218. message = wrapReturnCode(message);
  2219. message = message.replace("\n", "\r\n");
  2220. }
  2221. message = formatMsg(message, &fValue, &sValue, delegate string (char name) { mixin(S_TRACE);
  2222. auto dc = std.ascii.toUpper(name);
  2223. foreach (c, v; names) { mixin(S_TRACE);
  2224. if (std.ascii.toUpper(c) == dc) { mixin(S_TRACE);
  2225. return v;
  2226. }
  2227. }
  2228. return "";
  2229. }, (string path) { mixin(S_TRACE);
  2230. return comm.skin.findImagePath(path, comm.summary.scenarioPath).length != 0 || decodeFontPath(path) in comm.skin.spChars;
  2231. }, rFonts, rColors);
  2232. auto dmsg = to!dstring(message);
  2233. auto cr = d.getSystemColor(SWT.COLOR_RED);
  2234. auto cb = d.getSystemColor(SWT.COLOR_CYAN);
  2235. auto cg = d.getSystemColor(SWT.COLOR_GREEN);
  2236. auto cy = d.getSystemColor(SWT.COLOR_YELLOW);
  2237. auto co = new Color(d, new RGB(255, 165, 0)); scope (exit) co.dispose(); // CardWirth 1.50
  2238. auto cp = new Color(d, new RGB(204, 136, 255)); scope (exit) cp.dispose(); // CardWirth 1.50
  2239. auto cl = new Color(d, new RGB(169, 169, 169)); scope (exit) cl.dispose(); // CardWirth 1.50
  2240. auto cd = new Color(d, new RGB(105, 105, 105)); scope (exit) cd.dispose(); // CardWirth 1.50
  2241. auto font = new Font(d, dwtData(prop.looks.messageFont(legacy)));
  2242. scope (exit) font.dispose();
  2243. auto fc = new Color(d, dwtData(prop.var.etc.messageForeColor, alpha));
  2244. scope (exit) fc.dispose();
  2245. auto hc = new Color(d, dwtData(prop.var.etc.messageHemColor, alpha));
  2246. scope (exit) hc.dispose();
  2247. auto selFont = new Font(d, dwtData(prop.looks.messageSelectFont(legacy)));
  2248. scope (exit) selFont.dispose();
  2249. auto start = prop.looks.messageStartPos(legacy, talker !is null);
  2250. int x = start.x, y = start.y;
  2251. int lineH;
  2252. string old = "";
  2253. int msgLen = talker ? prop.looks.messageImageLen : prop.looks.messageLen;
  2254. int writeLen = 0;
  2255. void ret() { mixin(S_TRACE);
  2256. writeLen = 0;
  2257. x = start.x;
  2258. y += lineH;
  2259. old = "";
  2260. }
  2261. // ????????
  2262. auto wrgb = fc.getRGB();
  2263. void drawSPFont(GC gc, CPoint pt, string path, RGB c) { mixin(S_TRACE);
  2264. string fpath = comm.skin.findImagePath(path, sPath);
  2265. ImageData data = null;
  2266. if (fpath && fpath.length) { mixin(S_TRACE);
  2267. // ?????????
  2268. data = loadImage(fpath, true);
  2269. }
  2270. if (!data) { mixin(S_TRACE);
  2271. // ??????
  2272. data = spChar(comm.skin, decodeFontPath(path));
  2273. if (data) { mixin(S_TRACE);
  2274. auto spc = data;
  2275. data = new ImageData(spc.width, spc.height, 24, new PaletteData(0xFF << 16, 0xFF << 8, 0xFF << 0));
  2276. // &R????????
  2277. foreach (dx; 0 .. data.width) { mixin(S_TRACE);
  2278. foreach (dy; 0 .. data.height) { mixin(S_TRACE);
  2279. auto p = spc.palette.getRGB(spc.getPixel(dx, dy));
  2280. if (wrgb.opEquals(p)) { mixin(S_TRACE);
  2281. data.setPixel(dx, dy, (c.red << 16) | (c.green << 8) | (c.blue << 0));
  2282. } else { mixin(S_TRACE);
  2283. data.setPixel(dx, dy, (p.red << 16) | (p.green << 8) | (p.blue << 0));
  2284. }
  2285. }
  2286. }
  2287. data.transparentPixel = data.getPixel(0, 0);
  2288. }
  2289. }
  2290. if (data) { mixin(S_TRACE);
  2291. auto img = new Image(d, data);
  2292. scope (exit) img.dispose();
  2293. gc.drawImage(img, pt.x, pt.y);
  2294. }
  2295. }
  2296. if (legacy) { mixin(S_TRACE);
  2297. auto textCanvas = new Image(d, rect.width, rect.height + bh * sel.length);
  2298. scope (exit) textCanvas.dispose();
  2299. auto tgc = new GC(textCanvas);
  2300. scope (exit) tgc.dispose();
  2301. // FIXME: IPA???????????????????
  2302. // ?????????????????
  2303. // tgc.setTextAntialias(SWT.OFF);
  2304. tgc.setFont(font);
  2305. tgc.setForeground(fc);
  2306. tgc.setBackground(hc);
  2307. tgc.fillRectangle(0, 0, rect.width, rect.height + bh * sel.length);
  2308. lineH = tgc.getFontMetrics().getHeight() + 2;
  2309. for (size_t i = 0; i < dmsg.length; i++) { mixin(S_TRACE);
  2310. if (rect.height - 6 < y + lineH) { mixin(S_TRACE);
  2311. // ??????
  2312. break;
  2313. }
  2314. auto cf = i in rFonts;
  2315. if (cf) { mixin(S_TRACE);
  2316. // ????????????
  2317. string s1 = to!string(dmsg[i]);
  2318. i++;
  2319. string s2 = to!string(dmsg[i]);
  2320. auto w = (tgc.textExtent(s1).x - 1) + (tgc.textExtent(s2).x - 1);
  2321. if (msgLen < writeLen + 2) { mixin(S_TRACE);
  2322. // ??????
  2323. if (!(i + 1 < dmsg.length && dmsg[i + 1] == '\n')) { mixin(S_TRACE);
  2324. ret();
  2325. }
  2326. if (rect.height - 6 < y + lineH) { mixin(S_TRACE);
  2327. // ??????
  2328. break;
  2329. }
  2330. }
  2331. writeLen += 2;
  2332. drawSPFont(gc, CPoint(x - 2, y - 2), *cf, tgc.getForeground().getRGB());
  2333. x += w;
  2334. continue;
  2335. }
  2336. auto colorP = i in rColors;
  2337. if (colorP) { mixin(S_TRACE);
  2338. // ???????
  2339. switch (*colorP) {
  2340. case 'W': tgc.setForeground(fc); break;
  2341. case 'R': tgc.setForeground(cr); break;
  2342. case 'B': tgc.setForeground(cb); break;
  2343. case 'G': tgc.setForeground(cg); break;
  2344. case 'Y': tgc.setForeground(cy); break;
  2345. case 'O': tgc.setForeground(co); break;
  2346. case 'P': tgc.setForeground(cp); break;
  2347. case 'L': tgc.setForeground(cl); break;
  2348. case 'D': tgc.setForeground(cd); break;
  2349. default: assert (0);
  2350. }
  2351. i++;
  2352. continue;
  2353. }
  2354. auto c = dmsg[i];
  2355. switch (c) {
  2356. case '\n':
  2357. ret();
  2358. break;
  2359. default:
  2360. auto s = to!string(c);
  2361. auto te = tgc.textExtent(s);
  2362. int w = te.x - 1;
  2363. int len = (te.x + 1) / tgc.textExtent("#").x;
  2364. // ???????????????????(CardWirth??????????)
  2365. if (msgLen < writeLen + (s == " " ? len - 1 : len)) { mixin(S_TRACE);
  2366. // ??????
  2367. if (!(i + 1 < dmsg.length && dmsg[i + 1] == '\n')) { mixin(S_TRACE);
  2368. ret();
  2369. }
  2370. if (rect.height - 6 < y + lineH) { mixin(S_TRACE);
  2371. // ??????
  2372. break;
  2373. }
  2374. }
  2375. writeLen += len;
  2376. tgc.drawText(s, x, y, true);
  2377. x += w;
  2378. break;
  2379. }
  2380. }
  2381. // ???
  2382. tgc.setForeground(fc);
  2383. tgc.setFont(selFont);
  2384. auto slh = tgc.getFontMetrics().getHeight();
  2385. int sx;
  2386. int sy = rect.height + ((bh - slh) / 2);
  2387. foreach (i, t; sel) { mixin(S_TRACE);
  2388. sx = (rect.width - tgc.textExtent(t).x) / 2;
  2389. tgc.drawText(t, sx, sy, true);
  2390. sy += bh;
  2391. }
  2392. // ????
  2393. auto tImgData = textCanvas.getImageData();
  2394. tImgData.transparentPixel = tImgData.getPixel(0, 0);
  2395. auto hemImgData = new ImageData(tImgData.width, tImgData.height, 2, new PaletteData([new RGB(255, 255, 255), new RGB(0, 0, 0)]));
  2396. hemImgData.transparentPixel = 0;
  2397. foreach (ix; 0 .. tImgData.width) { mixin(S_TRACE);
  2398. foreach (iy; 0 .. tImgData.height) { mixin(S_TRACE);
  2399. if (tImgData.getPixel(ix, iy) != tImgData.transparentPixel) { mixin(S_TRACE);
  2400. hemImgData.setPixel(ix, iy, 1);
  2401. }
  2402. }
  2403. }
  2404. auto hemImg = new Image(d, hemImgData);
  2405. scope (exit) hemImg.dispose();
  2406. auto tImg = new Image(d, tImgData);
  2407. scope (exit) tImg.dispose();
  2408. gc.drawImage(hemImg, -1, -1);
  2409. gc.drawImage(hemImg, 0, -1);
  2410. gc.drawImage(hemImg, 1, -1);
  2411. gc.drawImage(hemImg, 1, 0);
  2412. gc.drawImage(hemImg, 1, 1);
  2413. gc.drawImage(hemImg, 0, 1);
  2414. gc.drawImage(hemImg, -1, 1);
  2415. gc.drawImage(hemImg, -1, 0);
  2416. gc.drawImage(tImg, 0, 0);
  2417. } else { mixin(S_TRACE);
  2418. // FIXME: IPA???????????????????
  2419. // ?????????????????
  2420. // gc.setTextAntialias(SWT.ON);
  2421. gc.setFont(font);
  2422. lineH = gc.getFontMetrics().getHeight();
  2423. gc.setForeground(fc);
  2424. void drawText(string s, int x, int y) { mixin(S_TRACE);
  2425. if ("?" == s && "?" == old) { mixin(S_TRACE);
  2426. // "?"?????????????????
  2427. gc.setForeground(hc);
  2428. gc.drawText(s, x, y - 1, true);
  2429. gc.drawText(s, x, y + 1, true);
  2430. gc.drawText(s, x - lineH / 2 + 2, y - 1, true);
  2431. gc.drawText(s, x - lineH / 2 + 2, y + 1, true);
  2432. gc.setForeground(fc);
  2433. gc.drawText(s, x - lineH / 2, y, true);
  2434. gc.drawText(s, x, y, true);
  2435. } else { mixin(S_TRACE);
  2436. gc.setForeground(hc);
  2437. gc.drawText(s, x - 1, y, true);
  2438. gc.drawText(s, x + 1, y, true);
  2439. gc.drawText(s, x, y - 1, true);
  2440. gc.drawText(s, x, y + 1, true);
  2441. gc.setForeground(fc);
  2442. gc.drawText(s, x, y, true);
  2443. }
  2444. old = s;
  2445. }
  2446. for (size_t i = 0; i < dmsg.length; i++) { mixin(S_TRACE);
  2447. if (rect.height - 6 < y + lineH) { mixin(S_TRACE);
  2448. // ??????
  2449. break;
  2450. }
  2451. auto cf = i in rFonts;
  2452. if (cf) { mixin(S_TRACE);
  2453. // ????????????
  2454. string s1 = to!string(dmsg[i]);
  2455. i++;
  2456. string s2 = to!string(dmsg[i]);
  2457. auto w = (gc.textExtent(s1).x - 1) + (gc.textExtent(s2).x - 1);
  2458. if (msgLen < writeLen + 2) { mixin(S_TRACE);
  2459. // ??????
  2460. if (!(i + 1 < dmsg.length && dmsg[i + 1] == '\n')) { mixin(S_TRACE);
  2461. ret();
  2462. }
  2463. if (rect.height - 6 < y + lineH) { mixin(S_TRACE);
  2464. // ??????
  2465. break;
  2466. }
  2467. }
  2468. writeLen += 2;
  2469. drawSPFont(gc, CPoint(x, y - 2), *cf, gc.getForeground().getRGB());
  2470. x += w;
  2471. continue;
  2472. }
  2473. auto colorP = i in rColors;
  2474. if (colorP) { mixin(S_TRACE);
  2475. // ???????
  2476. switch (*colorP) {
  2477. case 'W': gc.setForeground(fc); break;
  2478. case 'R': gc.setForeground(cr); break;
  2479. case 'B': gc.setForeground(cb); break;
  2480. case 'G': gc.setForeground(cg); break;
  2481. case 'Y': gc.setForeground(cy); break;
  2482. case 'O': gc.setForeground(co); break; // CardWirth 1.50
  2483. case 'P': gc.setForeground(cp); break; // CardWirth 1.50
  2484. case 'L': gc.setForeground(cl); break; // CardWirth 1.50
  2485. case 'D': gc.setForeground(cd); break; // CardWirth 1.50
  2486. default: assert (0);
  2487. }
  2488. i++;
  2489. continue;
  2490. }
  2491. auto c = dmsg[i];
  2492. switch (c) {
  2493. case '\n':
  2494. ret();
  2495. break;
  2496. default:
  2497. auto s = to!string(c);
  2498. auto te = gc.textExtent(s);
  2499. int w = te.x - 1;
  2500. int len = (te.x + 1) / gc.textExtent("#").x;
  2501. // ???????????????????(CardWirth??????????)
  2502. if (msgLen < writeLen + (s == " " ? len - 1 : len)) { mixin(S_TRACE);
  2503. // ??????
  2504. if (!(i + 1 < dmsg.length && dmsg[i + 1] == '\n')) { mixin(S_TRACE);
  2505. ret();
  2506. }
  2507. if (rect.height - 6 < y + lineH) { mixin(S_TRACE);
  2508. // ??????
  2509. break;
  2510. }
  2511. }
  2512. writeLen += len;
  2513. drawText(s, x, y);
  2514. x += w;
  2515. break;
  2516. }
  2517. }
  2518. // ???
  2519. gc.setForeground(fc);
  2520. gc.setFont(selFont);
  2521. auto slh = gc.getFontMetrics().getHeight();
  2522. int sx;
  2523. int sy = rect.height + ((bh - slh) / 2);
  2524. foreach (i, t; sel) { mixin(S_TRACE);
  2525. sx = (rect.width - gc.textExtent(t).x) / 2;
  2526. drawText(t, sx, sy);
  2527. sy += bh;
  2528. }
  2529. }
  2530. // ?
  2531. auto c1 = new Color(d, dwtData(prop.var.etc.messageLineColor1, alpha));
  2532. scope (exit) c1.dispose();
  2533. auto c2 = new Color(d, dwtData(prop.var.etc.messageLineColor2, alpha));
  2534. scope (exit) c2.dispose();
  2535. gc.setForeground(c1);
  2536. gc.drawRectangle(0, 0, rect.width - 1, rect.height - 1);
  2537. gc.drawRectangle(2, 2, rect.width - 5, rect.height - 5);
  2538. foreach (i; 0 .. sel.length) { mixin(S_TRACE);
  2539. gc.drawRectangle(0, rect.height + bh * i, rect.width - 1, bh - 1);
  2540. gc.drawRectangle(2, rect.height + 2 + bh * i, rect.width - 5, bh - 5);
  2541. }
  2542. gc.setForeground(c2);
  2543. gc.drawRectangle(1, 1, rect.width - 3, rect.height - 3);
  2544. foreach (i; 0 .. sel.length) { mixin(S_TRACE);
  2545. gc.drawRectangle(1, rect.height + 1 + bh * i, rect.width - 3, bh - 3);
  2546. }
  2547. return canvas.getImageData();
  2548. }