PageRenderTime 45ms CodeModel.GetById 4ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://bitbucket.org/k4nagatsuki/cwxeditor
D | 1125 lines | 1103 code | 19 blank | 3 comment | 360 complexity | d63f0163bfc060056a01c9cf147d369f MD5 | raw file
Possible License(s): LGPL-2.1
  1. module cwx.editor.gui.dwt.materialselect;
  2. import cwx.cwl;
  3. import cwx.utils;
  4. import cwx.summary;
  5. import cwx.skin;
  6. import cwx.menu;
  7. import cwx.types;
  8. import cwx.imagesize;
  9. import cwx.editor.gui.sound;
  10. import cwx.editor.gui.dwt.dprops;
  11. import cwx.editor.gui.dwt.dutils;
  12. import cwx.editor.gui.dwt.dskin;
  13. import cwx.editor.gui.dwt.centerlayout;
  14. import cwx.editor.gui.dwt.commons;
  15. import cwx.editor.gui.dwt.customtable;
  16. import cwx.editor.gui.dwt.dmenu;
  17. import cwx.editor.gui.dwt.incsearch;
  18. import std.array;
  19. import std.file;
  20. import std.path;
  21. import std.string;
  22. import std.conv;
  23. import org.eclipse.swt.all;
  24. public:
  25. enum MtType {
  26. CARD,
  27. BG_IMG,
  28. BGM,
  29. SE
  30. }
  31. class MaterialSelect(MtType Type, D, C) {
  32. /// ??????????????
  33. void delegate()[] modEvent;
  34. /// ???????????????
  35. void delegate(string file)[] includeEvent;
  36. public:
  37. this (Commons comm, Props prop, Summary summ, bool readOnly, void delegate() refresh, string[] defs, int including = -1, bool canInclude = false, bool isMenuCard = false) { mixin(S_TRACE);
  38. _readOnly = readOnly ? SWT.READ_ONLY : SWT.NONE;
  39. _comm = comm;
  40. _prop = prop;
  41. _summ = summ;
  42. if (_readOnly) _summSkin = findSkin(_comm, _prop, _summ);
  43. _refresh = refresh;
  44. _defs = defs;
  45. _including = including;
  46. _canInclude = canInclude;
  47. _isMenuCard = isMenuCard;
  48. }
  49. @property
  50. const
  51. bool canInclude() { return _canInclude; }
  52. @property
  53. const
  54. bool isMenuCard() { return _isMenuCard; }
  55. D createDirsCombo(Composite parent) { mixin(S_TRACE);
  56. static if (is (D == Combo)) {
  57. _dirs = new D(parent, SWT.BORDER | SWT.READ_ONLY | SWT.DROP_DOWN);
  58. _dirs.setVisibleItemCount(_prop.var.etc.comboVisibleItemCount);
  59. } else static if (is (D == CCombo)) {
  60. _dirs = new D(parent, SWT.BORDER | SWT.READ_ONLY);
  61. _dirs.setVisibleItemCount(_prop.var.etc.comboVisibleItemCount);
  62. createTextMenu!D(_comm, _prop, _dirs, null);
  63. } else { mixin(S_TRACE);
  64. static assert (0);
  65. }
  66. _dirs.setEnabled(!_readOnly);
  67. _dirs.addSelectionListener(new CSListener);
  68. _comm.refSkin.add(&refresh);
  69. _comm.refSkin.add(&refreshFileListMenu);
  70. _comm.refPaths.add(&__refPaths);
  71. _comm.refPath.add(&__refPath);
  72. _comm.delPaths.add(&__delPaths);
  73. _comm.replPath.add(&__replPath);
  74. _comm.refIgnorePaths.add(&refresh);
  75. static if (Type == MtType.BGM) {
  76. stopBGMEvent ~= &stopBGM;
  77. }
  78. _dirs.addDisposeListener(new class DisposeListener {
  79. override void widgetDisposed(DisposeEvent e) { mixin(S_TRACE);
  80. _comm.refSkin.remove(&refresh);
  81. _comm.refSkin.remove(&refreshFileListMenu);
  82. _comm.refPaths.remove(&__refPaths);
  83. _comm.refPath.remove(&__refPath);
  84. _comm.delPaths.remove(&__delPaths);
  85. _comm.replPath.remove(&__replPath);
  86. _comm.refIgnorePaths.remove(&refresh);
  87. static if (Type == MtType.BGM) {
  88. cwx.utils.remove(stopBGMEvent, &stopBGM);
  89. }
  90. }
  91. });
  92. auto menu = new Menu(_dirs.getShell(), SWT.POP_UP);
  93. createMenuItem(_comm, menu, MenuID.IncSearch, &startIncSearch, () => !_readOnly);
  94. _dirs.setMenu(menu);
  95. return _dirs;
  96. }
  97. static if (Type == MtType.BGM) {
  98. private void stopBGM() { mixin(S_TRACE);
  99. if (_playing) { mixin(S_TRACE);
  100. playBGM();
  101. }
  102. }
  103. }
  104. C createFileList(Composite parent) { mixin(S_TRACE);
  105. static if (is (C == Table)) {
  106. _fileList = new C(parent, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION | SWT.VIRTUAL);
  107. new FullTableColumn(_fileList, SWT.NONE);
  108. } else static if (is (C == Combo)) {
  109. _fileList = new C(parent, SWT.BORDER | SWT.READ_ONLY | SWT.DROP_DOWN);
  110. _fileList.setVisibleItemCount(_prop.var.etc.comboVisibleItemCount);
  111. } else static if (is (C == CCombo)) {
  112. _fileList = new C(parent, SWT.BORDER | SWT.READ_ONLY);
  113. _fileList.setVisibleItemCount(_prop.var.etc.comboVisibleItemCount);
  114. createTextMenu!CCombo(_comm, _prop, _fileList, null);
  115. } else { mixin(S_TRACE);
  116. static assert (0);
  117. }
  118. _fileList.setEnabled(!_readOnly);
  119. _fileList.addSelectionListener(new LSListener);
  120. static if (is (C == Table)) {
  121. static if (Type == MtType.BGM || Type == MtType.SE) {
  122. auto play = new Play;
  123. _fileList.addMouseListener(play);
  124. _fileList.addKeyListener(play);
  125. static if (Type == MtType.BGM) {
  126. _fileList.addDisposeListener(new StopBGM);
  127. } else static if (Type == MtType.SE) {
  128. _fileList.addDisposeListener(new StopSE);
  129. } else static assert (0);
  130. } else { mixin(S_TRACE);
  131. auto open = new OpenMaterial;
  132. _fileList.addMouseListener(open);
  133. _fileList.addKeyListener(open);
  134. }
  135. }
  136. refreshFileListMenu();
  137. new class(_fileList) FileDropTarget {
  138. this(Control c) { mixin(S_TRACE);
  139. super(c);
  140. }
  141. protected override:
  142. bool canDrop() {return _summ !is null && !_readOnly;}
  143. string[] doAll(string[] files) { mixin(S_TRACE);
  144. assert (_summ !is null);
  145. string[] r;
  146. foreach (f; files) { mixin(S_TRACE);
  147. if (isTarg(f) && !hasPath(_summ.scenarioPath, f)) { mixin(S_TRACE);
  148. r ~= f;
  149. }
  150. }
  151. if (r.length > 0) { mixin(S_TRACE);
  152. auto dlg = new MessageBox(control.getShell(), SWT.ICON_QUESTION | SWT.YES | SWT.NO);
  153. if (1 == r.length) { mixin(S_TRACE);
  154. dlg.setMessage(.tryFormat(_prop.msgs.dlgMsgDropFile, r[0]));
  155. } else { mixin(S_TRACE);
  156. dlg.setMessage(.tryFormat(_prop.msgs.dlgMsgDropFiles, r.length));
  157. }
  158. dlg.setText(_prop.msgs.dlgTitDropFiles);
  159. if (SWT.YES == dlg.open()) { mixin(S_TRACE);
  160. return r;
  161. }
  162. }
  163. return [];
  164. }
  165. bool doFile(string path, int x, int y) { mixin(S_TRACE);
  166. assert (_summ !is null);
  167. auto cur = currentDir;
  168. if (!cur) cur = summSkin.materialPath;
  169. copyTo(_summ.scenarioPath, path, cur, false);
  170. return true;
  171. }
  172. void doExit() { mixin(S_TRACE);
  173. assert (_summ !is null);
  174. auto cur = currentDir;
  175. if (!cur) cur = summSkin.materialPath;
  176. refreshPaths(summSkin.materialPath);
  177. _comm.refPaths.call(this.outer, summSkin.materialPath);
  178. }
  179. };
  180. _incSearch = new IncSearch(_comm, parent);
  181. _incSearch.modEvent ~= { mixin(S_TRACE);
  182. refreshList();
  183. };
  184. return _fileList;
  185. }
  186. private void refreshFileListMenu() { mixin(S_TRACE);
  187. if (!_fileList) return;
  188. auto menu = new Menu(_fileList.getShell(), SWT.POP_UP);
  189. createMenuItem(_comm, menu, MenuID.IncSearch, &startIncSearch, () => !_readOnly);
  190. new MenuItem(menu, SWT.SEPARATOR);
  191. createMenuItem(_comm, menu, MenuID.OpenAtFileView, &openFilePath, () => filePath.length > 0 && !_readOnly);
  192. createMenuItem(_comm, menu, MenuID.CopyFilePath, &copyFilePath, () => filePath.length > 0);
  193. static if (Type == MtType.CARD) {
  194. if (!_readOnly && _canInclude && _summ && _summ.legacy) { mixin(S_TRACE);
  195. new MenuItem(menu, SWT.SEPARATOR);
  196. createMenuItem(_comm, menu, MenuID.IncludeImage, &includeImage, () => filePath.length > 0 && !_readOnly);
  197. }
  198. } else static if (Type == MtType.BGM) {
  199. new MenuItem(menu, SWT.SEPARATOR);
  200. _bgmMenu = createMenuItem(_comm, menu, MenuID.PlayBGM, &playBGM, &canPlay);
  201. auto data = cast(MenuData) _bgmMenu.getData();
  202. data.format = (string t) {return data.id is MenuID.StopBGM ? .tryFormat(t, _playing) : t;};
  203. } else static if (Type == MtType.SE) {
  204. new MenuItem(menu, SWT.SEPARATOR);
  205. createMenuItem(_comm, menu, MenuID.PlaySE, &playSE, &canPlay);
  206. createMenuItem(_comm, menu, MenuID.StopSE, &stopSE, null);
  207. }
  208. _fileList.setMenu(menu);
  209. }
  210. static if (Type == MtType.CARD) {
  211. @property
  212. void useNoCardSizeImage(bool noCardSize) { mixin(S_TRACE);
  213. if (_noCardSize == noCardSize) return;
  214. _noCardSize = noCardSize;
  215. if (!_noCardSize && !isBinImg(filePath)) { mixin(S_TRACE);
  216. auto p = summSkin.findImagePath(path, _summ ? _summ.scenarioPath : "");
  217. if (p.length) { mixin(S_TRACE);
  218. uint w, h;
  219. imageSize(p, w, h);
  220. auto cs = _prop.looks.cardSize;
  221. if (cs.width != w || cs.height != h) { mixin(S_TRACE);
  222. path = "";
  223. }
  224. }
  225. }
  226. refresh();
  227. }
  228. @property
  229. const
  230. bool useNoCardSizeImage() { mixin(S_TRACE);
  231. return _noCardSize;
  232. }
  233. private void includeImage() { mixin(S_TRACE);
  234. if (!_canInclude) return;
  235. string file = filePath;
  236. if (!file.length) return;
  237. auto dlg = new MessageBox(_fileList.getShell(), SWT.ICON_QUESTION | SWT.YES | SWT.NO);
  238. dlg.setText(_prop.msgs.dlgTitQuestion);
  239. dlg.setMessage(.tryFormat(_prop.msgs.dlgMsgIncludeImage, this.path));
  240. if (SWT.YES == dlg.open()) { mixin(S_TRACE);
  241. try { mixin(S_TRACE);
  242. if (!file.exists()) return;
  243. _binPath = bImgToStr(cast(ubyte[])readBinary(file));
  244. refreshDefs();
  245. selectDir(_including);
  246. foreach (d; includeEvent) { mixin(S_TRACE);
  247. d(file);
  248. }
  249. } catch (Exception e) {
  250. debugln(e);
  251. }
  252. }
  253. }
  254. @property
  255. uint pcNumber() { mixin(S_TRACE);
  256. if (!_isMenuCard || !_summ || !_summ.legacy) return 0;
  257. auto sel = _dirs.getSelectionIndex();
  258. if (0 <= _including) { mixin(S_TRACE);
  259. sel--;
  260. }
  261. if (0 < sel && sel <= _prop.var.etc.partyMax) { mixin(S_TRACE);
  262. return sel;
  263. }
  264. return 0;
  265. }
  266. @property
  267. void pcNumber(uint pcNum) { mixin(S_TRACE);
  268. if (0 == pcNum) return;
  269. if (!_isMenuCard || !_summ || !_summ.legacy) return;
  270. uint num = pcNum;
  271. if (0 <= _including) { mixin(S_TRACE);
  272. num++;
  273. }
  274. _dirs.select(num);
  275. }
  276. }
  277. private void refreshDefs() { mixin(S_TRACE);
  278. if (!_canInclude) { mixin(S_TRACE);
  279. refreshPaths();
  280. return;
  281. }
  282. string[] defs = [_prop.msgs.imageNone];
  283. int including = _including;
  284. static if (Type == MtType.CARD) {
  285. uint pcNum = pcNumber;
  286. }
  287. if (isBinImg(_binPath)) { mixin(S_TRACE);
  288. including = defs.length;
  289. defs ~= _prop.msgs.imageIncluding;
  290. }
  291. static if (Type == MtType.CARD) {
  292. if (_isMenuCard && _summ && _summ.legacy) { mixin(S_TRACE);
  293. foreach (num; 0 .. _prop.var.etc.partyMax) { mixin(S_TRACE);
  294. defs ~= .tryFormat(_prop.msgs.pcNumber, num + 1);
  295. }
  296. if (pcNum <= 0 || _prop.var.etc.partyMax < pcNum) { mixin(S_TRACE);
  297. pcNum = 0;
  298. }
  299. } else { mixin(S_TRACE);
  300. pcNum = 0;
  301. }
  302. }
  303. if (defs != _defs) { mixin(S_TRACE);
  304. _defs = defs;
  305. _including = including;
  306. static if (Type == MtType.CARD) {
  307. pcNumber = pcNum;
  308. }
  309. }
  310. refreshPaths();
  311. }
  312. static if (Type == MtType.BGM || Type == MtType.SE) {
  313. private Button _bgmBtn;
  314. }
  315. static if (Type == MtType.BGM) {
  316. private MenuItem _bgmMenu;
  317. private ToolItem _bgmTMenu;
  318. string _playing = null;
  319. void createPlayToolItem(ToolBar bar) { mixin(S_TRACE);
  320. _bgmTMenu = createToolItem(_comm, bar, MenuID.PlayBGM, &playBGM, &canPlay, SWT.CHECK);
  321. auto data = cast(MenuData) _bgmTMenu.getData();
  322. data.format = (string t) {return data.id is MenuID.StopBGM ? .tryFormat(t, _playing) : t;};
  323. }
  324. Button createPlayButton(Composite parent) { mixin(S_TRACE);
  325. _bgmBtn = new Button(parent, SWT.TOGGLE);
  326. _bgmBtn.setLayoutData(new GridData);
  327. _bgmBtn.setToolTipText(_prop.buildTool(MenuID.PlayBGM));
  328. _bgmBtn.setImage(_prop.images.menu(MenuID.PlayBGM));
  329. auto pbgm = new Play;
  330. _bgmBtn.addSelectionListener(pbgm);
  331. _comm.put(_bgmBtn, &canPlay);
  332. return _bgmBtn;
  333. }
  334. @property
  335. bool canPlay() { mixin(S_TRACE);
  336. return _playing ? true : filePath.length > 0;
  337. }
  338. void playBGM() { mixin(S_TRACE);
  339. string p = filePath;
  340. if (p.length > 0 && (!_playing || !cfnmatch(nabs(p), nabs(_playing)))) { mixin(S_TRACE);
  341. bool inPlay = playBGMCW(_prop, p, _summ.legacy);
  342. if (inPlay) { mixin(S_TRACE);
  343. _playing = p;
  344. auto relPath = .encodePath(this.path);
  345. if (_bgmMenu) { mixin(S_TRACE);
  346. _bgmMenu.setText(.tryFormat(_prop.buildMenu(MenuID.StopBGM), .baseName(relPath)));
  347. auto d = cast(MenuData) _bgmMenu.getData();
  348. d.id = MenuID.StopBGM;
  349. _bgmMenu.setImage(_prop.images.menu(MenuID.StopBGM));
  350. _bgmMenu.setSelection(true);
  351. }
  352. if (_bgmTMenu) { mixin(S_TRACE);
  353. _bgmTMenu.setToolTipText(.tryFormat(_prop.buildTool(MenuID.StopBGM), relPath));
  354. _bgmTMenu.setImage(_prop.images.menu(MenuID.StopBGM));
  355. _bgmTMenu.setSelection(true);
  356. }
  357. if (_bgmBtn) { mixin(S_TRACE);
  358. _bgmBtn.setToolTipText(.tryFormat(_prop.buildTool(MenuID.StopBGM), relPath));
  359. _bgmBtn.setImage(_prop.images.menu(MenuID.StopBGM));
  360. _bgmBtn.setSelection(true);
  361. }
  362. return;
  363. }
  364. }
  365. if (_bgmMenu) { mixin(S_TRACE);
  366. _bgmMenu.setText(_prop.buildMenu(MenuID.PlayBGM));
  367. auto d = cast(MenuData) _bgmMenu.getData();
  368. d.id = MenuID.PlayBGM;
  369. _bgmMenu.setImage(_prop.images.menu(MenuID.PlayBGM));
  370. _bgmMenu.setSelection(false);
  371. }
  372. if (_bgmTMenu) { mixin(S_TRACE);
  373. _bgmTMenu.setToolTipText(_prop.buildTool(MenuID.PlayBGM));
  374. _bgmTMenu.setImage(_prop.images.menu(MenuID.PlayBGM));
  375. _bgmTMenu.setSelection(false);
  376. }
  377. if (_bgmBtn) { mixin(S_TRACE);
  378. _bgmBtn.setToolTipText(_prop.buildTool(MenuID.PlayBGM));
  379. _bgmBtn.setImage(_prop.images.menu(MenuID.PlayBGM));
  380. _bgmBtn.setSelection(false);
  381. }
  382. .stopBGM();
  383. _playing = null;
  384. }
  385. private class Play : SelectionAdapter, KeyListener, MouseListener {
  386. override void mouseUp(MouseEvent e) {}
  387. override void mouseDown(MouseEvent e) {}
  388. override void mouseDoubleClick(MouseEvent e) { mixin(S_TRACE);
  389. if (e.button == 1) { mixin(S_TRACE);
  390. playBGM();
  391. }
  392. }
  393. override void keyReleased(KeyEvent e) {}
  394. override void keyPressed(KeyEvent e) { mixin(S_TRACE);
  395. if (e.character == SWT.CR) { mixin(S_TRACE);
  396. playBGM();
  397. }
  398. }
  399. override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  400. playBGM();
  401. }
  402. }
  403. } else static if (Type == MtType.SE) {
  404. void createPlayToolItem(ToolBar bar) { mixin(S_TRACE);
  405. createToolItem(_comm, bar, MenuID.PlaySE, &playSE, &canPlay);
  406. }
  407. Button createPlayButton(Composite parent) { mixin(S_TRACE);
  408. _bgmBtn = new Button(parent, SWT.PUSH);
  409. _bgmBtn.setToolTipText(_prop.buildTool(MenuID.PlaySE));
  410. _bgmBtn.setImage(_prop.images.menu(MenuID.PlaySE));
  411. auto play = new Play;
  412. _bgmBtn.addSelectionListener(play);
  413. _comm.put(_bgmBtn, &canPlay);
  414. return _bgmBtn;
  415. }
  416. Button createStopButton(Composite parent) { mixin(S_TRACE);
  417. auto stop = new Button(parent, SWT.PUSH);
  418. stop.setToolTipText(_prop.buildTool(MenuID.StopSE));
  419. stop.setImage(_prop.images.menu(MenuID.StopSE));
  420. auto sse = new StopSE;
  421. stop.addSelectionListener(sse);
  422. stop.addDisposeListener(sse);
  423. return stop;
  424. }
  425. @property
  426. bool canPlay() { mixin(S_TRACE);
  427. return filePath.length > 0;
  428. }
  429. void playSE() { mixin(S_TRACE);
  430. string p = filePath;
  431. if (p.length > 0) { mixin(S_TRACE);
  432. playSECW(_prop, p, _summ.legacy);
  433. }
  434. }
  435. void stopSE() { mixin(S_TRACE);
  436. .stopSE();
  437. }
  438. private class Play : SelectionAdapter, KeyListener, MouseListener {
  439. override void mouseUp(MouseEvent e) {}
  440. override void mouseDown(MouseEvent e) {}
  441. override void mouseDoubleClick(MouseEvent e) { mixin(S_TRACE);
  442. if (e.button == 1) { mixin(S_TRACE);
  443. playSE();
  444. }
  445. }
  446. override void keyReleased(KeyEvent e) {}
  447. override void keyPressed(KeyEvent e) { mixin(S_TRACE);
  448. if (e.character == SWT.CR) { mixin(S_TRACE);
  449. playSE();
  450. }
  451. }
  452. override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  453. playSE();
  454. }
  455. }
  456. }
  457. Button createRefreshButton(Composite parent, bool text) { mixin(S_TRACE);
  458. auto refBtn = new Button(parent, SWT.PUSH);
  459. refBtn.setImage(_prop.images.menu(MenuID.Refresh));
  460. if (text) { mixin(S_TRACE);
  461. refBtn.setText(_prop.msgs.refreshS);
  462. } else { mixin(S_TRACE);
  463. refBtn.setToolTipText(_prop.buildTool(MenuID.Refresh));
  464. }
  465. refBtn.addSelectionListener(new RSListener);
  466. return refBtn;
  467. }
  468. Button createDirectoryButton(Composite parent, bool text) { mixin(S_TRACE);
  469. _dirBtn = new Button(parent, SWT.PUSH);
  470. _dirBtn.setLayoutData(new GridData(GridData.FILL_VERTICAL));
  471. _dirBtn.setImage(_prop.images.folder);
  472. _dirBtn.addSelectionListener(new DSListener);
  473. if (text) { mixin(S_TRACE);
  474. _dirBtn.setText(_prop.buildTool(MenuID.OpenDir));
  475. } else { mixin(S_TRACE);
  476. _dirBtn.setToolTipText(_prop.buildTool(MenuID.OpenDir));
  477. }
  478. return _dirBtn;
  479. }
  480. @property
  481. string path() { mixin(S_TRACE);
  482. if (_dirs.getSelectionIndex() == _including && isBinImg(_binPath)) { mixin(S_TRACE);
  483. return _binPath;
  484. }
  485. return _path;
  486. }
  487. @property
  488. string filePath() { mixin(S_TRACE);
  489. if (!_dirs || _dirs.isDisposed()) return "";
  490. if (!_fileList || _fileList.isDisposed()) return "";
  491. if (_dirs.getSelectionIndex() == _including && isBinImg(_binPath)) { mixin(S_TRACE);
  492. return _binPath;
  493. }
  494. auto p = currentDir;
  495. if (p && _fileList.getSelectionIndex() >= 0) { mixin(S_TRACE);
  496. string f = fileText(_fileList.getItem(_fileList.getSelectionIndex()));
  497. if (_dirs.getSelectionIndex() == _tbl) { mixin(S_TRACE);
  498. return std.path.buildPath(defDir, f);
  499. } else { mixin(S_TRACE);
  500. return std.path.buildPath(std.path.buildPath(_summ ? _summ.scenarioPath : "", p), f);
  501. }
  502. }
  503. return "";
  504. }
  505. @property
  506. void path(string path) { mixin(S_TRACE);
  507. path2(path, true);
  508. }
  509. void path2(string path, bool updateBinImg) { mixin(S_TRACE);
  510. auto old = _path;
  511. scope (exit) {
  512. if (old != _path) {
  513. foreach (dlg; modEvent) dlg();
  514. }
  515. }
  516. _path = path;
  517. if (updateBinImg) {
  518. _binPath = isBinImg(path) ? path : "";
  519. }
  520. static if (Type is MtType.CARD) {
  521. if (!useNoCardSizeImage && !_binPath.length) { mixin(S_TRACE);
  522. auto p = summSkin.findImagePath(_path, _summ ? _summ.scenarioPath : "");
  523. if (p.length) { mixin(S_TRACE);
  524. uint w, h;
  525. imageSize(p, w, h);
  526. auto cs = _prop.looks.cardSize;
  527. if (cs.width != w || cs.height != h) { mixin(S_TRACE);
  528. useNoCardSizeImage = true;
  529. if (_refresh) _refresh();
  530. }
  531. }
  532. }
  533. }
  534. refreshDefs();
  535. }
  536. @property
  537. string binPath() { mixin(S_TRACE);
  538. return _binPath;
  539. }
  540. @property
  541. D dirsCombo() { mixin(S_TRACE);
  542. return _dirs;
  543. }
  544. @property
  545. C fileList() { mixin(S_TRACE);
  546. return _fileList;
  547. }
  548. void refresh() { mixin(S_TRACE);
  549. refreshDefs();
  550. if (_refresh) _refresh();
  551. }
  552. @property
  553. string[] showingNames() { mixin(S_TRACE);
  554. static if (is(C : Table)) {
  555. TableItem[] itms;
  556. if (_fnone) { mixin(S_TRACE);
  557. itms = _fileList.getItems()[1 .. $];
  558. } else { mixin(S_TRACE);
  559. itms = _fileList.getItems();
  560. }
  561. auto r = new string[itms.length];
  562. foreach (i, ref s; r) { mixin(S_TRACE);
  563. s = itms[i].getText();
  564. }
  565. return r;
  566. } else static if (is(C : Combo) || is(C : CCombo)) {
  567. if (_fnone) { mixin(S_TRACE);
  568. return _fileList.getItems()[1 .. $];
  569. } else { mixin(S_TRACE);
  570. return _fileList.getItems();
  571. }
  572. }
  573. }
  574. @property
  575. string[] showingPaths() { mixin(S_TRACE);
  576. string[] r;
  577. string curr = currentDir;
  578. string[] paths = showingNames;
  579. foreach (s; paths) { mixin(S_TRACE);
  580. if (curr) { mixin(S_TRACE);
  581. r ~= .encodePath(std.path.buildPath(curr, s));
  582. } else if (s.startsWith("/")) { mixin(S_TRACE);
  583. string file;
  584. s = s["/".length .. $];
  585. int i = s.lastIndexOf("/");
  586. if (i != -1) { mixin(S_TRACE);
  587. file = s[i + "/".length .. $];
  588. s = s[0 .. i];
  589. } else { mixin(S_TRACE);
  590. file = s;
  591. s = "";
  592. }
  593. r ~= .encodePath(std.path.buildPath(s, file));
  594. } else { mixin(S_TRACE);
  595. r ~= s;
  596. }
  597. }
  598. return r;
  599. }
  600. void copyFilePath() { mixin(S_TRACE);
  601. auto p = path;
  602. if (!p.length) return;
  603. _comm.clipboard.setContents([new PathString(encodePath(p))],
  604. [TextTransfer.getInstance()]);
  605. _comm.refreshToolBar();
  606. }
  607. @property
  608. bool selectedDefDir() { mixin(S_TRACE);
  609. return _selDir == _tbl;
  610. }
  611. @property
  612. void selectDir(int sel) { mixin(S_TRACE);
  613. _dirs.select(sel);
  614. refreshList();
  615. scope (exit) {
  616. refreshButtons();
  617. if (_refresh) _refresh();
  618. }
  619. if (sel < _defs.length) { mixin(S_TRACE);
  620. _path = "";
  621. if (_selDir != sel) { mixin(S_TRACE);
  622. foreach (dlg; modEvent) dlg();
  623. }
  624. _selDir = sel;
  625. } else { mixin(S_TRACE);
  626. static if (is(C : Combo) || is(C : CCombo)) {
  627. auto old = _path;
  628. scope (exit) {
  629. if (old != _path) {
  630. foreach (dlg; modEvent) dlg();
  631. }
  632. }
  633. string p = currentDir;
  634. if (!p) return;
  635. if (0 == _fileList.getItemCount()) return;
  636. _fileList.select(0);
  637. _path = std.path.buildPath(p, _fileList.getItem(0));
  638. }
  639. _selDir = sel;
  640. }
  641. }
  642. @property
  643. IncSearch incSearch() {return _incSearch;}
  644. void startIncSearch() { mixin(S_TRACE);
  645. .forceFocus(_fileList, true);
  646. _incSearch.startIncSearch();
  647. }
  648. private:
  649. static if (Type == MtType.CARD) {
  650. private bool _noCardSize = false;
  651. @property string defExt() {return summSkin.extImage;}
  652. @property string defDir() {return summSkin.tableDir;}
  653. bool isTarg(string p) {return summSkin.isCardImage(p, _noCardSize);}
  654. bool hasTarg(string p) {return summSkin.hasCardImage(p, _noCardSize);}
  655. string[] targsImpl(string dir, bool re) {return summSkin.cards(dir, _prop.var.etc.logicalSort, re, _noCardSize);}
  656. @property Image image() {return _prop.images.cards;}
  657. } else static if (Type == MtType.BG_IMG) {
  658. @property string defExt() {return summSkin.extImage;}
  659. @property string defDir() {return summSkin.tableDir;}
  660. bool isTarg(string p) {return summSkin.isBgImage(p);}
  661. bool hasTarg(string p) {return summSkin.hasBgImage(p);}
  662. string[] targsImpl(string dir, bool re) {return summSkin.tables(dir, _prop.var.etc.logicalSort, re);}
  663. @property Image image() {return _prop.images.backs;}
  664. } else static if (Type == MtType.BGM) {
  665. @property string defExt() {return summSkin.extBgm;}
  666. @property string defDir() {return summSkin.bgmDir;}
  667. bool isTarg(string p) {return summSkin.isBGM(p);}
  668. bool hasTarg(string p) {return summSkin.hasBGM(p);}
  669. string[] targsImpl(string dir, bool re) {return summSkin.musics(dir, _prop.var.etc.logicalSort, re);}
  670. @property Image image() {return _prop.images.bgm;}
  671. } else static if (Type == MtType.SE) {
  672. @property string defExt() {return summSkin.extSound;}
  673. @property string defDir() {return summSkin.seDir;}
  674. bool isTarg(string p) {return summSkin.isSE(p);}
  675. bool hasTarg(string p) {return summSkin.hasSE(p);}
  676. string[] targsImpl(string dir, bool re) {return summSkin.sounds(dir, _prop.var.etc.logicalSort, re);}
  677. @property Image image() {return _prop.images.se;}
  678. } else static assert (0);
  679. class RSListener : SelectionAdapter {
  680. public override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  681. refreshPaths(null, true);
  682. if (_refresh) _refresh();
  683. }
  684. }
  685. class DSListener : SelectionAdapter {
  686. public override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  687. if (_dirs.getSelectionIndex() == _tbl) { mixin(S_TRACE);
  688. openFolder(defDir);
  689. } else if (_summ) { mixin(S_TRACE);
  690. string cur = currentDir;
  691. if (cur) { mixin(S_TRACE);
  692. openFolder(std.path.buildPath(_summ.scenarioPath, cur));
  693. } else { mixin(S_TRACE);
  694. scope p = std.path.buildPath(_summ.scenarioPath, summSkin.materialPath);
  695. if (exists(p)) { mixin(S_TRACE);
  696. openFolder(p);
  697. } else { mixin(S_TRACE);
  698. openFolder(_summ.scenarioPath);
  699. }
  700. }
  701. }
  702. }
  703. }
  704. class CSListener : SelectionAdapter {
  705. public override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  706. selectDir(_dirs.getSelectionIndex());
  707. }
  708. }
  709. class LSListener : SelectionAdapter {
  710. public override void widgetSelected(SelectionEvent e) { mixin(S_TRACE);
  711. int index = _fileList.getSelectionIndex();
  712. if (index < 0) return;
  713. auto old = _path;
  714. scope (exit) {
  715. if (old != _path) {
  716. foreach (dlg; modEvent) dlg();
  717. }
  718. refreshButtons();
  719. }
  720. if (_allList) { mixin(S_TRACE);
  721. string s = fileText(_fileList.getItem(index));
  722. string file;
  723. if (s.startsWith("/")) { mixin(S_TRACE);
  724. s = s["/".length .. $];
  725. int i = s.lastIndexOf("/");
  726. if (i != -1) { mixin(S_TRACE);
  727. file = s[i + "/".length .. $];
  728. s = s[0 .. i];
  729. } else { mixin(S_TRACE);
  730. file = s;
  731. s = "/";
  732. }
  733. _dirs.setText(s);
  734. } else { mixin(S_TRACE);
  735. _dirs.select(_tbl);
  736. file = s;
  737. }
  738. refreshList();
  739. int selIndex = -1;
  740. foreach (i, itm; _fileList.getItems()) { mixin(S_TRACE);
  741. if (cfnmatch(fileText(itm), file)) { mixin(S_TRACE);
  742. selIndex = i;
  743. break;
  744. }
  745. }
  746. _fileList.select(selIndex);
  747. static if (is (C == Table)) {
  748. _fileList.showSelection();
  749. }
  750. string p = currentDir;
  751. _path = std.path.buildPath(p, file);
  752. _selDir = _dirs.getSelectionIndex();
  753. if (_refresh) _refresh();
  754. } else { mixin(S_TRACE);
  755. string p = currentDir;
  756. if (!p) { mixin(S_TRACE);
  757. static if (is(C : Combo) || is(C : CCombo)) {
  758. if (index == 0) return;
  759. _fileList.remove(0);
  760. }
  761. _dirs.select(_defs.length);
  762. p = currentDir;
  763. }
  764. if (p) { mixin(S_TRACE);
  765. _path = std.path.buildPath(p, fileText(_fileList.getItem(_fileList.getSelectionIndex())));
  766. _selDir = _dirs.getSelectionIndex();
  767. if (_refresh) _refresh();
  768. }
  769. }
  770. }
  771. }
  772. private class OpenMaterial : MouseAdapter, KeyListener {
  773. override void mouseDoubleClick(MouseEvent e) { mixin(S_TRACE);
  774. if (1 == e.button) { mixin(S_TRACE);
  775. openFilePath();
  776. }
  777. }
  778. override void keyReleased(KeyEvent e) {}
  779. override void keyPressed(KeyEvent e) { mixin(S_TRACE);
  780. if (SWT.CR == e.character) openFilePath();
  781. }
  782. }
  783. private void openFilePath() { mixin(S_TRACE);
  784. auto dir = _dirs.getSelectionIndex();
  785. if (dir < _defs.length) return;
  786. if (dir == _tbl) return;
  787. auto p = filePath;
  788. if (p.length) { mixin(S_TRACE);
  789. _comm.openFilePath(p, false);
  790. }
  791. }
  792. private static string fromViewPath(string s) { mixin(S_TRACE);
  793. static if (dirSeparator != "/" && altDirSeparator == "/") {
  794. return replace(s, "/", dirSeparator);
  795. } else { mixin(S_TRACE);
  796. return s;
  797. }
  798. }
  799. private static string toViewPath(string s) { mixin(S_TRACE);
  800. static if (dirSeparator != "/" && altDirSeparator == "/") {
  801. return replace(replace(s, dirSeparator, "/"), altDirSeparator, "/");
  802. } else { mixin(S_TRACE);
  803. return s;
  804. }
  805. }
  806. @property
  807. private string currentDir() { mixin(S_TRACE);
  808. int sel = _dirs.getSelectionIndex();
  809. if (sel >= _defs.length) { mixin(S_TRACE);
  810. if (sel == _tbl) { mixin(S_TRACE);
  811. return "";
  812. } else { mixin(S_TRACE);
  813. return _dirs.getText() == "/" ? "" : toViewPath(_dirs.getText());
  814. }
  815. }
  816. return null;
  817. }
  818. private string fileText(T)(T itm) { mixin(S_TRACE);
  819. static if (is(T : TableItem)) {
  820. return itm.getText();
  821. } else static if (is(T : string)) {
  822. return itm;
  823. } else static assert (0);
  824. }
  825. int indexOf(T)(T list, string path) { mixin(S_TRACE);
  826. foreach (i, s; list.getItems()) { mixin(S_TRACE);
  827. if (cfnmatch(fileText(s), path)) { mixin(S_TRACE);
  828. return i;
  829. }
  830. }
  831. return -1;
  832. }
  833. int flIndexOf(string path) { mixin(S_TRACE);
  834. return indexOf(_fileList, path);
  835. }
  836. int dirsIndexOf(string path) { mixin(S_TRACE);
  837. return indexOf(_dirs, path);
  838. }
  839. string[] targs(string path, bool forceRefresh) { mixin(S_TRACE);
  840. string[] r;
  841. foreach (f; targsImpl(path, forceRefresh)) { mixin(S_TRACE);
  842. if (_incSearch.match(f.baseName())) { mixin(S_TRACE);
  843. r ~= f;
  844. }
  845. }
  846. return r;
  847. }
  848. void __refreshList(string path, bool forceRefresh) { mixin(S_TRACE);
  849. __refreshListImpl(targs(path, forceRefresh));
  850. _allList = false;
  851. }
  852. void __refreshList(string[] paths, bool forceRefresh) { mixin(S_TRACE);
  853. string[] tgs;
  854. foreach (path; paths) { mixin(S_TRACE);
  855. string parent;
  856. if (cfnmatch(path, defDir)) { mixin(S_TRACE);
  857. parent = "";
  858. } else { mixin(S_TRACE);
  859. assert (_summ !is null);
  860. parent = abs2rel(path, _summ.scenarioPath);
  861. parent = dirSeparator.idup ~ parent;
  862. }
  863. string[] s = targs(path, forceRefresh);
  864. foreach (ref f; s) { mixin(S_TRACE);
  865. f = encodePath(std.path.buildPath(parent, f));
  866. }
  867. tgs ~= s;
  868. }
  869. __refreshListImpl(tgs);
  870. _allList = true;
  871. }
  872. void __refreshListImpl(string[] tgs) { mixin(S_TRACE);
  873. foreach (f; tgs) { mixin(S_TRACE);
  874. static if (is(C : Table)) {
  875. auto itm = new TableItem(_fileList, SWT.NONE);
  876. itm.setText(f);
  877. itm.setImage(image);
  878. } else static if (is(C : Combo) || is(C : CCombo)) {
  879. _fileList.add(f);
  880. } else static assert (0);
  881. }
  882. string sel = _path.length > 0 ? baseName(_path) : "";
  883. if (sel.length > 0 && _dirs.getSelectionIndex() == _selDir) { mixin(S_TRACE);
  884. int index = flIndexOf(sel);
  885. if (index >= 0) { mixin(S_TRACE);
  886. _fileList.select(index);
  887. } else if (_dirs.getSelectionIndex() == _tbl) { mixin(S_TRACE);
  888. index = flIndexOf(setExtension(sel, defExt));
  889. if (index >= 0) _fileList.select(index);
  890. }
  891. }
  892. static if (is (C == Table)) {
  893. _fileList.showSelection();
  894. } else static if (!is (C == Combo) && !is (C == CCombo)) {
  895. static assert (false);
  896. }
  897. }
  898. @property
  899. string[] allDirs() { mixin(S_TRACE);
  900. string[] st;
  901. foreach (i; _defs.length .. _dirs.getItemCount()) { mixin(S_TRACE);
  902. string t = _dirs.getItem(i);
  903. if (i == _tbl) { mixin(S_TRACE);
  904. st ~= defDir;
  905. } else if (t == "/") { mixin(S_TRACE);
  906. assert (_summ !is null);
  907. st ~= nabs(_summ.scenarioPath);
  908. } else { mixin(S_TRACE);
  909. assert (_summ !is null);
  910. st ~= nabs(std.path.buildPath(_summ.scenarioPath, fromViewPath(t)));
  911. }
  912. }
  913. return st;
  914. }
  915. void refreshList(bool forceRefresh = false) { mixin(S_TRACE);
  916. _fileList.removeAll();
  917. _fnone = false;
  918. if (_dirs.getSelectionIndex() < _defs.length) { mixin(S_TRACE);
  919. auto dirs = allDirs;
  920. if (!dirs.length) { mixin(S_TRACE);
  921. _fileList.setEnabled(false);
  922. } else { mixin(S_TRACE);
  923. _fileList.setEnabled(!_readOnly);
  924. __refreshList(dirs, forceRefresh);
  925. static if (is(C : Combo) || is(C : CCombo)) {
  926. _fileList.add(_prop.msgs.fileNone, 0);
  927. _fileList.select(0);
  928. _fnone = true;
  929. } else { mixin(S_TRACE);
  930. _fileList.select(-1);
  931. }
  932. }
  933. } else if (_dirs.getSelectionIndex() == _tbl) { mixin(S_TRACE);
  934. __refreshList(defDir, forceRefresh);
  935. } else if (_summ) { mixin(S_TRACE);
  936. string st;
  937. if (_dirs.getText() == "/") { mixin(S_TRACE);
  938. st = _summ.scenarioPath;
  939. } else { mixin(S_TRACE);
  940. st = std.path.buildPath(_summ.scenarioPath, fromViewPath(_dirs.getText()));
  941. }
  942. __refreshList(st, forceRefresh);
  943. }
  944. }
  945. void searchTarg(string dir, size_t cut) { mixin(S_TRACE);
  946. if (hasTarg(dir)) { mixin(S_TRACE);
  947. _dirs.add(dir.length <= cut ? "/" : toViewPath(dir[cut .. $]));
  948. }
  949. foreach (f; clistdir(dir)) { mixin(S_TRACE);
  950. if (containsPath(_prop.var.etc.ignorePaths, f)) continue;
  951. f = std.path.buildPath(dir, f);
  952. if (isDir(f)) { mixin(S_TRACE);
  953. searchTarg(f, cut);
  954. }
  955. }
  956. }
  957. void refreshPaths(string select = null, bool forceRefresh = false) { mixin(S_TRACE);
  958. int oldSel = _dirs.getSelectionIndex();
  959. if (oldSel < 0) oldSel = 0;
  960. string oldSelS = _dirs.getText();
  961. _dirs.removeAll();
  962. foreach (def; _defs) { mixin(S_TRACE);
  963. _dirs.add(def);
  964. }
  965. auto tbl = defDir;
  966. _tbl = -1;
  967. if (hasTarg(tbl)) { mixin(S_TRACE);
  968. _tbl = _dirs.getItemCount();
  969. _dirs.add(_prop.msgs.pathDef);
  970. }
  971. size_t cut = 0;
  972. if (_summ) { mixin(S_TRACE);
  973. string st = _summ.scenarioPath;
  974. cut = st.length;
  975. static if (altDirSeparator.length) {
  976. if (!endsWith(st, dirSeparator) && !endsWith(st, altDirSeparator)) cut++;
  977. } else { mixin(S_TRACE);
  978. if (!endsWith(st, dirSeparator)) cut++;
  979. }
  980. searchTarg(_summ.scenarioPath, cut);
  981. }
  982. if (!select) { mixin(S_TRACE);
  983. void selectOld() { mixin(S_TRACE);
  984. if (oldSel < _defs.length) { mixin(S_TRACE);
  985. _dirs.select(oldSel);
  986. } else { mixin(S_TRACE);
  987. int index = dirsIndexOf(oldSelS);
  988. if (index >= 0) { mixin(S_TRACE);
  989. _dirs.select(index);
  990. } else if (_dirs.getItemCount() > 0) { mixin(S_TRACE);
  991. _dirs.select(0);
  992. }
  993. }
  994. }
  995. bool def;
  996. if (isBinImg(_path)) { mixin(S_TRACE);
  997. _dirs.select(_including);
  998. } else { mixin(S_TRACE);
  999. auto p = summSkin.findPathF(_path, defExt, defDir, _summ ? _summ.scenarioPath : "", def);
  1000. if (p.length > 0) { mixin(S_TRACE);
  1001. if (def) { mixin(S_TRACE);
  1002. if (_tbl == -1) { mixin(S_TRACE);
  1003. // ???????
  1004. selectOld();
  1005. } else { mixin(S_TRACE);
  1006. _dirs.select(_tbl);
  1007. }
  1008. } else if (_summ) { mixin(S_TRACE);
  1009. string pt = dirName(p);
  1010. pt = pt.length <= cut ? dirSeparator.idup : pt[cut .. $];
  1011. pt = toViewPath(pt);
  1012. _dirs.select(dirsIndexOf(pt));
  1013. }
  1014. } else { mixin(S_TRACE);
  1015. selectOld();
  1016. }
  1017. }
  1018. } else { mixin(S_TRACE);
  1019. select = toViewPath(select);
  1020. _dirs.setText(select);
  1021. }
  1022. _selDir = _dirs.getSelectionIndex();
  1023. refreshList(forceRefresh);
  1024. }
  1025. void __refPaths(Object sender, string parent) { mixin(S_TRACE);
  1026. if (this !is sender) { mixin(S_TRACE);
  1027. refreshPaths();
  1028. }
  1029. if (_refresh) _refresh();
  1030. }
  1031. void __refPath(string o, string n, bool isDir) { mixin(S_TRACE);
  1032. auto old = _path;
  1033. scope (exit) {
  1034. if (old != _path) {
  1035. foreach (dlg; modEvent) dlg();
  1036. }
  1037. }
  1038. if (isDir) { mixin(S_TRACE);
  1039. int i = _defs.length;
  1040. if (_tbl >= 0) i++;
  1041. for (; i < _dirs.getItemCount(); i++) { mixin(S_TRACE);
  1042. string name = fromViewPath(_dirs.getItem(i));
  1043. if (startsWith(name, o)) { mixin(S_TRACE);
  1044. string nName = std.path.buildPath(n, name[o.length .. $]);
  1045. nName = toViewPath(nName);
  1046. _dirs.setItem(i, nName);
  1047. if (i == _dirs.getSelectionIndex()) { mixin(S_TRACE);
  1048. _dirs.setText(nName);
  1049. }
  1050. }
  1051. }
  1052. } else { mixin(S_TRACE);
  1053. if (o == _path) _path = n;
  1054. int di = _dirs.getSelectionIndex();
  1055. auto op = o;
  1056. if (di >= 0 && cfnmatch(fromViewPath(_dirs.getItems()[di]), dirName(o))) { mixin(S_TRACE);
  1057. int index = flIndexOf(baseName(o));
  1058. if (index >= 0) { mixin(S_TRACE);
  1059. string nName = baseName(n);
  1060. static if (is(C : Table)) {
  1061. _fileList.getItem(index).setText(nName);
  1062. } else static if (is (C : Combo) || is (C : CCombo)) {
  1063. _fileList.setItem(index, nName);
  1064. _fileList.setText(nName);
  1065. } else static assert (0);
  1066. }
  1067. }
  1068. }
  1069. if (_refresh) _refresh();
  1070. }
  1071. void __delPaths() { mixin(S_TRACE);
  1072. refreshPaths();
  1073. }
  1074. void __replPath(string from, string to) { mixin(S_TRACE);
  1075. if (_path == from) { mixin(S_TRACE);
  1076. refreshPaths();
  1077. }
  1078. }
  1079. void refreshButtons() { mixin(S_TRACE);
  1080. _comm.refreshToolBar();
  1081. }
  1082. @property
  1083. Skin summSkin() { mixin(S_TRACE);
  1084. return _summSkin ? _summSkin : _comm.skin;
  1085. }
  1086. int _readOnly = 0;
  1087. Props _prop;
  1088. Commons _comm;
  1089. D _dirs;
  1090. Summary _summ;
  1091. Button _dirBtn;
  1092. IncSearch _incSearch;
  1093. string _path = "";
  1094. string _binPath = "";
  1095. string[] _defs;
  1096. int _selDir;
  1097. int _including = -1;
  1098. bool _canInclude = false;
  1099. bool _isMenuCard = false;
  1100. int _tbl = -1;
  1101. bool _fnone = false;
  1102. C _fileList;
  1103. bool _allList = false;
  1104. void delegate() _refresh;
  1105. Skin _summSkin;
  1106. }