DictionaryWindow.cs 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288
  1. using FastReport.Controls;
  2. using FastReport.Data;
  3. using FastReport.Forms;
  4. using FastReport.Utils;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.ComponentModel;
  8. using System.Drawing;
  9. using System.Reflection;
  10. using System.Text;
  11. using System.Windows.Forms;
  12. namespace FastReport.Design.ToolWindows
  13. {
  14. /// <summary>
  15. /// Represents the "Data Dictionary" window.
  16. /// </summary>
  17. public class DictionaryWindow : FilterableToolWindow
  18. {
  19. #region Fields
  20. private ToolbarDropDownButton btnActions;
  21. private ToolbarButton btnEdit;
  22. private ToolbarButton btnDelete;
  23. private ToolbarButton btnView;
  24. private ContextMenuItem miNew;
  25. private ContextMenuItem miOpen;
  26. private ContextMenuItem miMerge;
  27. private ContextMenuItem miSave;
  28. private ContextMenuItem miChooseData;
  29. private ContextMenuItem miSortDataSources;
  30. private ContextMenuItem miUploadDataSource;
  31. private ContextMenuItem miNewDataSource;
  32. private ContextMenuItem miNewRelation;
  33. private ContextMenuItem miNewParameter;
  34. private ContextMenuItem miNewTotal;
  35. private ContextMenuItem miNewCalculatedColumn;
  36. private ContextMenuItem miCopyDataSource;
  37. private ContextMenuBase mnuContext;
  38. private ContextMenuItem miSortDataSources1;
  39. private ContextMenuItem miUploadDataSource1;
  40. private ContextMenuItem miNewDataSource1;
  41. private ContextMenuItem miNewParameter1;
  42. private ContextMenuItem miNewTotal1;
  43. private ContextMenuItem miNewCalculatedColumn1;
  44. private ContextMenuItem miRename;
  45. private ContextMenuItem miEdit;
  46. private ContextMenuItem miDelete;
  47. private ContextMenuItem miDeleteAlias;
  48. private ContextMenuItem miView;
  49. private ContextMenuItem miViewJson;
  50. private ContextMenuItem miSortDataFields;
  51. private Panel dragIndicator;
  52. private Splitter splitter;
  53. private DescriptionControl lblDescription;
  54. private Report report;
  55. private List<string> expandedNodes;
  56. private bool updating;
  57. private static DraggedItemCollection draggedItems = new DraggedItemCollection();
  58. #endregion
  59. #region Properties
  60. private bool IsDataComponent
  61. {
  62. get { return tree.SelectedNode != null && tree.SelectedNode.Tag is DataComponentBase; }
  63. }
  64. private bool IsVariable
  65. {
  66. get
  67. {
  68. return tree.SelectedNode != null && tree.SelectedNode.Tag is Parameter &&
  69. !(tree.SelectedNode.Parent.Tag is SystemVariables);
  70. }
  71. }
  72. private bool IsTotal
  73. {
  74. get { return tree.SelectedNode != null && tree.SelectedNode.Tag is Total; }
  75. }
  76. private bool IsConnection
  77. {
  78. get { return tree.SelectedNode != null && tree.SelectedNode.Tag is DataConnectionBase; }
  79. }
  80. private bool IsTable
  81. {
  82. get { return tree.SelectedNode != null && tree.SelectedNode.Tag is DataSourceBase; }
  83. }
  84. private bool IsJsonTable
  85. {
  86. get { return tree.SelectedNode != null && tree.SelectedNode.Tag is FastReport.Data.JsonConnection.JsonTableDataSource; }
  87. }
  88. private bool IsRelation
  89. {
  90. get { return tree.SelectedNode != null && tree.SelectedNode.Tag is Relation; }
  91. }
  92. private bool IsEditableColumn
  93. {
  94. get
  95. {
  96. TreeNode node = tree.SelectedNode;
  97. bool result = node != null && node.Tag is Column;
  98. if (result)
  99. {
  100. // check if column belongs to the datasource, not relation.
  101. while (node != null)
  102. {
  103. if (node.Tag is Relation)
  104. {
  105. result = false;
  106. break;
  107. }
  108. else if (node.Tag is DataSourceBase)
  109. break;
  110. node = node.Parent;
  111. }
  112. }
  113. return result;
  114. }
  115. }
  116. private bool IsCube
  117. {
  118. get { return tree.SelectedNode != null && tree.SelectedNode.Tag is CubeSourceBase; }
  119. }
  120. private bool IsDataSources
  121. {
  122. get { return tree.SelectedNode != null && tree.SelectedNode.Tag == report.Dictionary.DataSources; }
  123. }
  124. private bool IsVariables
  125. {
  126. get { return tree.SelectedNode != null && tree.SelectedNode.Tag == report.Dictionary.Parameters; }
  127. }
  128. private bool IsSystemVariables
  129. {
  130. get { return tree.SelectedNode != null && tree.SelectedNode.Tag == report.Dictionary.SystemVariables; }
  131. }
  132. private bool IsTotals
  133. {
  134. get { return tree.SelectedNode != null && tree.SelectedNode.Tag == report.Dictionary.Totals; }
  135. }
  136. private bool IsCubeSources
  137. {
  138. get { return tree.SelectedNode != null && tree.SelectedNode.Tag == report.Dictionary.CubeSources; }
  139. }
  140. private bool CanEdit
  141. {
  142. get
  143. {
  144. return (IsDataComponent || IsVariable || IsTotal) &&
  145. !Designer.Restrictions.DontEditData &&
  146. (tree.SelectedNode.Tag as Base).HasFlag(Flags.CanEdit) &&
  147. !(tree.SelectedNode.Tag as Base).HasRestriction(Restrictions.DontEdit);
  148. }
  149. }
  150. private bool CanDelete
  151. {
  152. get
  153. {
  154. return (IsDataComponent || IsVariable || IsTotal) &&
  155. !Designer.Restrictions.DontEditData &&
  156. (tree.SelectedNode.Tag as Base).HasFlag(Flags.CanDelete) &&
  157. !(tree.SelectedNode.Tag as Base).HasRestriction(Restrictions.DontDelete);
  158. }
  159. }
  160. private bool CanCreateCalculatedColumn
  161. {
  162. get
  163. {
  164. return tree.SelectedNode != null && tree.SelectedNode.Tag is DataSourceBase;
  165. }
  166. }
  167. private bool IsAliased
  168. {
  169. get
  170. {
  171. return tree.SelectedNode != null && tree.SelectedNode.Tag is DataComponentBase &&
  172. (tree.SelectedNode.Tag as DataComponentBase).IsAliased;
  173. }
  174. }
  175. #endregion
  176. #region Private Methods
  177. private TreeNode FindNode(TreeNodeCollection parent, string text)
  178. {
  179. foreach (TreeNode node in parent)
  180. {
  181. if (node.Text == text)
  182. return node;
  183. }
  184. return null;
  185. }
  186. private void NavigateTo(string path)
  187. {
  188. string[] parts = path.Split('.');
  189. TreeNodeCollection parent = tree.Nodes;
  190. TreeNode node = null;
  191. foreach (string part in parts)
  192. {
  193. node = FindNode(parent, part);
  194. if (node == null)
  195. break;
  196. node.Expand();
  197. parent = node.Nodes;
  198. }
  199. tree.SelectedNode = node;
  200. }
  201. private void GetExpandedNodes(TreeNodeCollection nodes)
  202. {
  203. foreach (TreeNode node in nodes)
  204. {
  205. if (node.IsExpanded)
  206. expandedNodes.Add(node.FullPath);
  207. GetExpandedNodes(node.Nodes);
  208. }
  209. }
  210. private bool CompareNodes(TreeNodeCollection fromNodes, TreeNodeCollection toNodes)
  211. {
  212. if (fromNodes.Count != toNodes.Count)
  213. return false;
  214. for (int i = 0; i < fromNodes.Count; i++)
  215. {
  216. if (fromNodes[i].Text != toNodes[i].Text || fromNodes[i].ImageIndex != toNodes[i].ImageIndex)
  217. return false;
  218. toNodes[i].Tag = fromNodes[i].Tag;
  219. if (!CompareNodes(fromNodes[i].Nodes, toNodes[i].Nodes))
  220. return false;
  221. }
  222. return true;
  223. }
  224. private void CopyNodes(TreeNodeCollection fromNodes, TreeNodeCollection toNodes)
  225. {
  226. foreach (TreeNode fromNode in fromNodes)
  227. {
  228. TreeNode toNode = toNodes.Add(fromNode.Text);
  229. toNode.Tag = fromNode.Tag;
  230. toNode.ImageIndex = fromNode.ImageIndex;
  231. toNode.SelectedImageIndex = fromNode.SelectedImageIndex;
  232. CopyNodes(fromNode.Nodes, toNode.Nodes);
  233. if (expandedNodes.Contains(fromNode.FullPath))
  234. toNode.Expand();
  235. }
  236. }
  237. protected override void UpdateTree()
  238. {
  239. expandedNodes.Clear();
  240. GetExpandedNodes(tree.Nodes);
  241. TreeView buffer = new TreeView();
  242. if (report != null)
  243. {
  244. bool canShowData = report.Dictionary.Connections.Count > 0;
  245. foreach (DataSourceBase data in report.Dictionary.DataSources)
  246. {
  247. if (data.Enabled)
  248. {
  249. canShowData = true;
  250. break;
  251. }
  252. }
  253. bool canShowCube = report.Dictionary.CubeSources.Count > 0;
  254. TreeNode rootNode = null;
  255. if (canShowData)
  256. {
  257. rootNode = buffer.Nodes.Add(Res.Get("Designer,ToolWindow,Dictionary,DataSources"));
  258. rootNode.Tag = report.Dictionary.DataSources;
  259. rootNode.ImageIndex = 53;
  260. rootNode.SelectedImageIndex = rootNode.ImageIndex;
  261. DataTreeHelper.CreateDataTree(report.Dictionary, rootNode.Nodes, true, true, true, true);
  262. }
  263. // system variables
  264. rootNode = buffer.Nodes.Add(Res.Get("Designer,ToolWindow,Dictionary,SystemVariables"));
  265. rootNode.Tag = report.Dictionary.SystemVariables;
  266. rootNode.ImageIndex = 60;
  267. rootNode.SelectedImageIndex = rootNode.ImageIndex;
  268. DataTreeHelper.CreateVariablesTree(report.Dictionary.SystemVariables, rootNode.Nodes);
  269. // totals
  270. rootNode = buffer.Nodes.Add(Res.Get("Designer,ToolWindow,Dictionary,Totals"));
  271. rootNode.Tag = report.Dictionary.Totals;
  272. rootNode.ImageIndex = 132;
  273. rootNode.SelectedImageIndex = rootNode.ImageIndex;
  274. DataTreeHelper.CreateTotalsTree(report.Dictionary.Totals, rootNode.Nodes);
  275. // parameters
  276. rootNode = buffer.Nodes.Add(Res.Get("Designer,ToolWindow,Dictionary,Parameters"));
  277. rootNode.Tag = report.Dictionary.Parameters;
  278. rootNode.ImageIndex = 234;
  279. rootNode.SelectedImageIndex = rootNode.ImageIndex;
  280. DataTreeHelper.CreateParametersTree(report.Dictionary.Parameters, rootNode.Nodes);
  281. // functions
  282. rootNode = buffer.Nodes.Add(Res.Get("Designer,ToolWindow,Dictionary,Functions"));
  283. rootNode.ImageIndex = 52;
  284. rootNode.SelectedImageIndex = rootNode.ImageIndex;
  285. DataTreeHelper.CreateFunctionsTree(report, rootNode.Nodes);
  286. if (canShowCube)
  287. {
  288. rootNode = buffer.Nodes.Add(Res.Get("Designer,ToolWindow,Dictionary,CubeSources"));
  289. rootNode.Tag = report.Dictionary.CubeSources;
  290. rootNode.ImageIndex = 248;
  291. rootNode.SelectedImageIndex = rootNode.ImageIndex;
  292. DataTreeHelper.CreateCubeTree(report.Dictionary, rootNode.Nodes, false);
  293. }
  294. }
  295. if (!CompareNodes(buffer.Nodes, tree.Nodes))
  296. {
  297. tree.BeginUpdate();
  298. tree.Nodes.Clear();
  299. CopyNodes(buffer.Nodes, tree.Nodes);
  300. tree.EndUpdate();
  301. }
  302. buffer.Dispose();
  303. UpdateControls();
  304. }
  305. private void Change()
  306. {
  307. Designer.SetModified(this, "EditData");
  308. }
  309. private void UpdateControls()
  310. {
  311. btnEdit.Enabled = CanEdit;
  312. btnDelete.Enabled = CanDelete;
  313. btnView.Enabled = IsTable && !IsJsonTable;
  314. }
  315. private void miNew_Click(object sender, EventArgs e)
  316. {
  317. report.Dictionary.Clear();
  318. report.Dictionary.ReRegisterData();
  319. UpdateTree();
  320. Change();
  321. #if !WPF
  322. SearchMatches();
  323. #endif
  324. }
  325. private void miOpen_Click(object sender, EventArgs e)
  326. {
  327. using (OpenFileDialog dialog = new OpenFileDialog())
  328. {
  329. dialog.Filter = Res.Get("FileFilters,Dictionary");
  330. if (dialog.ShowDialog() == DialogResult.OK)
  331. {
  332. report.Dictionary.Load(dialog.FileName);
  333. UpdateTree();
  334. Change();
  335. #if !WPF
  336. SearchMatches();
  337. #endif
  338. }
  339. }
  340. }
  341. private void miSave_Click(object sender, EventArgs e)
  342. {
  343. using (SaveFileDialog dialog = new SaveFileDialog())
  344. {
  345. dialog.Filter = Res.Get("FileFilters,Dictionary");
  346. dialog.DefaultExt = "frd";
  347. dialog.FileName = "Dictionary.frd";
  348. if (dialog.ShowDialog() == DialogResult.OK)
  349. report.Dictionary.Save(dialog.FileName);
  350. }
  351. }
  352. private void miMerge_Click(object sender, EventArgs e)
  353. {
  354. using (OpenFileDialog dialog = new OpenFileDialog())
  355. {
  356. dialog.Filter = Res.Get("FileFilters,Dictionary");
  357. if (dialog.ShowDialog() == DialogResult.OK)
  358. {
  359. Dictionary dict = new Dictionary();
  360. dict.SetReport(report);
  361. dict.Load(dialog.FileName);
  362. foreach (Base obj in dict.AllObjects)
  363. {
  364. obj.SetReport(report);
  365. }
  366. report.Dictionary.Merge(dict);
  367. UpdateTree();
  368. Change();
  369. #if !WPF
  370. SearchMatches();
  371. #endif
  372. }
  373. }
  374. }
  375. private void btnActions_DropDownOpening(object sender, EventArgs e)
  376. {
  377. miNew.Enabled = Designer.cmdChooseData.Enabled;
  378. miOpen.Enabled = Designer.cmdChooseData.Enabled;
  379. miMerge.Enabled = Designer.cmdChooseData.Enabled;
  380. miSave.Enabled = Designer.cmdChooseData.Enabled;
  381. miChooseData.Enabled = Designer.cmdChooseData.Enabled;
  382. miSortDataSources.Enabled = Designer.cmdSortDataSources.Enabled;
  383. miUploadDataSource.Enabled = IsConnection;
  384. miNewDataSource.Enabled = Designer.cmdAddData.Enabled;
  385. miNewRelation.Enabled = Designer.cmdChooseData.Enabled;
  386. miNewParameter.Enabled = Designer.cmdChooseData.Enabled;
  387. miNewTotal.Enabled = Designer.cmdChooseData.Enabled;
  388. miNewCalculatedColumn.Enabled = Designer.cmdChooseData.Enabled && CanCreateCalculatedColumn;
  389. }
  390. private void mnuContext_Opening(object sender, CancelEventArgs e)
  391. {
  392. mnuContext.Clear();
  393. if (!Designer.cmdChooseData.Enabled)
  394. {
  395. e.Cancel = true;
  396. return;
  397. }
  398. if (IsDataSources || IsConnection)
  399. {
  400. if (Designer.cmdAddData.Enabled)
  401. mnuContext.AddItem(miNewDataSource1);
  402. if (Designer.cmdSortDataSources.Enabled)
  403. mnuContext.AddItem(miSortDataSources1);
  404. if (IsConnection)
  405. {
  406. mnuContext.AddItem(miCopyDataSource);
  407. if (!string.IsNullOrEmpty((tree.SelectedNode.Tag as DataConnectionBase).CloudId))
  408. miUploadDataSource.Text = Res.Get("Designer,ToolWindow,Dictionary,UploadChangesDataSource");
  409. else
  410. miUploadDataSource.Text = Res.Get("Designer,ToolWindow,Dictionary,UploadDataSource");
  411. mnuContext.AddItem(miUploadDataSource1);
  412. }
  413. }
  414. else if (IsVariables || IsVariable)
  415. mnuContext.AddItem(miNewParameter1);
  416. else if (IsTotals || IsTotal)
  417. mnuContext.AddItem(miNewTotal1);
  418. else if (CanCreateCalculatedColumn)
  419. {
  420. mnuContext.AddItem(miNewCalculatedColumn1);
  421. miNewCalculatedColumn.Enabled = true;
  422. }
  423. if (CanEdit)
  424. mnuContext.AddItem(miEdit);
  425. if (IsTable || IsEditableColumn || IsVariable || IsTotal)
  426. mnuContext.AddItem(miRename);
  427. if (CanDelete)
  428. mnuContext.AddItem(miDelete);
  429. if (IsAliased)
  430. mnuContext.AddItem(miDeleteAlias);
  431. if (IsTable || IsJsonTable)
  432. {
  433. mnuContext.AddItem(IsJsonTable ? miViewJson : miView);
  434. DataSourceBase data = tree.SelectedNode.Tag as DataSourceBase;
  435. if (data != null && data.Columns.Count > 1)
  436. {
  437. mnuContext.AddItem(miSortDataFields);
  438. }
  439. }
  440. // .Net: update menu item images
  441. mnuContext.ImageList = Designer.GetImages();
  442. e.Cancel = mnuContext.IsEmpty;
  443. }
  444. private void miNewRelation_Click(object sender, EventArgs e)
  445. {
  446. Relation relation = new Relation();
  447. report.Dictionary.Relations.Add(relation);
  448. using (RelationEditorForm form = new RelationEditorForm(relation))
  449. {
  450. if (form.ShowDialog() == DialogResult.OK)
  451. {
  452. relation.Name = report.Dictionary.CreateUniqueName(relation.ParentDataSource.Name + "_" +
  453. relation.ChildDataSource.Name);
  454. UpdateTree();
  455. Change();
  456. #if !WPF
  457. SearchMatches();
  458. #endif
  459. }
  460. else
  461. relation.Dispose();
  462. }
  463. }
  464. private void miNewCalculatedColumn_Click(object sender, EventArgs e)
  465. {
  466. DataSourceBase data = tree.SelectedNode.Tag as DataSourceBase;
  467. Column c = new Column();
  468. c.Name = data.Columns.CreateUniqueName("Column");
  469. c.Alias = data.Columns.CreateUniqueAlias(c.Alias);
  470. c.Calculated = true;
  471. data.Columns.Add(c);
  472. UpdateTree();
  473. string navigatePath = Res.Get("Designer,ToolWindow,Dictionary,DataSources");
  474. if (data.Parent is DataConnectionBase)
  475. navigatePath += "." + data.Parent.Name + "." + data.Alias;
  476. else
  477. navigatePath += GetPath(data);
  478. navigatePath += "." + c.Alias;
  479. NavigateTo(navigatePath);
  480. Change();
  481. #if !WPF
  482. SearchMatches();
  483. #endif
  484. }
  485. private string GetPath(Base data)
  486. {
  487. if (data == null || data.Name == "")
  488. return "";
  489. if (data.Parent is DataConnectionBase && data.Parent.Parent == null)
  490. return data.Parent.Alias;
  491. else
  492. return GetPath(data.Parent) + "." + data.Name;
  493. }
  494. private void miNewParameter_Click(object sender, EventArgs e)
  495. {
  496. Parameter p = new Parameter();
  497. ParameterCollection parent = null;
  498. if (IsVariable)
  499. parent = (tree.SelectedNode.Tag as Parameter).Parameters;
  500. else
  501. parent = report.Dictionary.Parameters;
  502. p.Name = parent.CreateUniqueName("Parameter");
  503. parent.Add(p);
  504. UpdateTree();
  505. NavigateTo(Res.Get("Designer,ToolWindow,Dictionary,Parameters") + "." + p.FullName);
  506. Change();
  507. #if !WPF
  508. SearchMatches();
  509. #endif
  510. }
  511. private void miNewTotal_Click(object sender, EventArgs e)
  512. {
  513. using (TotalEditorForm form = new TotalEditorForm(Designer))
  514. {
  515. if (form.ShowDialog() == DialogResult.OK)
  516. {
  517. report.Dictionary.Totals.Add(form.Total);
  518. UpdateTree();
  519. NavigateTo(Res.Get("Designer,ToolWindow,Dictionary,Totals") + "." + form.Total.Name);
  520. Change();
  521. #if !WPF
  522. SearchMatches();
  523. #endif
  524. }
  525. }
  526. }
  527. private void miRename_Click(object sender, EventArgs e)
  528. {
  529. if (tree.SelectedNode == null)
  530. return;
  531. tree.SelectedNode.BeginEdit();
  532. }
  533. private void miEdit_Click(object sender, EventArgs e)
  534. {
  535. if (!CanEdit)
  536. return;
  537. IHasEditor c = tree.SelectedNode.Tag as IHasEditor;
  538. if (c != null && c.InvokeEditor())
  539. {
  540. UpdateTree();
  541. Change();
  542. #if !WPF
  543. SearchMatches();
  544. #endif
  545. }
  546. }
  547. private void miDelete_Click(object sender, EventArgs e)
  548. {
  549. TreeNode parentNode = tree.SelectedNode?.Parent;
  550. if (parentNode == null)
  551. return;
  552. int index = parentNode.Nodes.IndexOf(tree.SelectedNode);
  553. for (int i = 0; i < tree.SelectedNodes.Count; i++)
  554. {
  555. if (CanDelete)
  556. {
  557. (tree.SelectedNode.Tag as Base).Delete();
  558. tree.SelectedNode.Remove();
  559. tree.SelectedNodes.RemoveAt(0);
  560. i--;
  561. }
  562. }
  563. index = Math.Min(index, parentNode.Nodes.Count - 1);
  564. tree.SelectedNode = index >= 0 ? parentNode.Nodes[index] : null;
  565. Change();
  566. }
  567. private void miDeleteAlias_Click(object sender, EventArgs e)
  568. {
  569. if (!IsAliased)
  570. return;
  571. DataComponentBase c = tree.SelectedNode.Tag as DataComponentBase;
  572. c.Alias = c.Name;
  573. tree.SelectedNode.Text = c.Name;
  574. Change();
  575. }
  576. private void miView_Click(object sender, EventArgs e)
  577. {
  578. if (!IsTable)
  579. return;
  580. DataSourceBase data = tree.SelectedNode.Tag as DataSourceBase;
  581. if (data == null)
  582. return;
  583. try
  584. {
  585. data.Init();
  586. }
  587. catch (Exception ex)
  588. {
  589. FRMessageBox.Error(ex.Message);
  590. return;
  591. }
  592. object dataSource = null;
  593. if (data is TableDataSource)
  594. {
  595. dataSource = (data as TableDataSource).Table;
  596. }
  597. else
  598. dataSource = data.Rows;
  599. if (dataSource == null)
  600. return;
  601. using (DataViewForm form = new DataViewForm(data))
  602. {
  603. form.ShowDialog();
  604. }
  605. }
  606. private void miViewJson_Click(object sender, EventArgs e)
  607. {
  608. if (!IsJsonTable)
  609. return;
  610. Data.JsonConnection.JsonTableDataSource data = tree.SelectedNode.Tag as Data.JsonConnection.JsonTableDataSource;
  611. if (data == null)
  612. return;
  613. try
  614. {
  615. data.Init();
  616. }
  617. catch (Exception ex)
  618. {
  619. FRMessageBox.Error(ex.Message);
  620. return;
  621. }
  622. using (JsonEditorForm jsonEditorForm = new JsonEditorForm())
  623. {
  624. StringBuilder sb = new StringBuilder();
  625. data.Json.WriteTo(sb, 2);
  626. jsonEditorForm.JsonText = sb.ToString();
  627. jsonEditorForm.SetToReadOnly();
  628. jsonEditorForm.ShowDialog();
  629. }
  630. }
  631. private void miUploadDataSource_Click(object sender, EventArgs e)
  632. {
  633. if (tree.SelectedNode.Tag is DataConnectionBase data)
  634. CloudCommands.UploadDataConnection(data);
  635. }
  636. private void miCopyDataSource_Click(object sender, EventArgs e)
  637. {
  638. if (tree.SelectedNode.Tag is DataConnectionBase)
  639. {
  640. DataConnectionBase data = tree.SelectedNode.Tag as DataConnectionBase;
  641. data.Clone();
  642. }
  643. Change();
  644. UpdateTree();
  645. Refresh();
  646. //Designer.SetModified();
  647. #if !WPF
  648. SearchMatches();
  649. #endif
  650. }
  651. private void miSortDataFields_Click(object sender, EventArgs e)
  652. {
  653. if (!IsTable)
  654. return;
  655. TableDataSource data = tree.SelectedNode.Tag as TableDataSource;
  656. if (data == null)
  657. return;
  658. if (data.Columns.Count > 1)
  659. {
  660. data.Columns.Sort();
  661. UpdateTree();
  662. Change();
  663. #if !WPF
  664. SearchMatches();
  665. #endif
  666. }
  667. }
  668. private void tree_KeyDown(object sender, KeyEventArgs e)
  669. {
  670. if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.F2)
  671. miRename_Click(this, null);
  672. else if (e.KeyCode == Keys.Delete)
  673. miDelete_Click(this, null);
  674. }
  675. private void tree_SelectionChanged(object sender, EventArgs e)
  676. {
  677. if (updating)
  678. return;
  679. Designer.SelectedObjects.Clear();
  680. foreach (var node in tree.SelectedNodes)
  681. {
  682. if (node.Tag is Base c)
  683. Designer.SelectedObjects.Add(c);
  684. }
  685. Designer.SelectionChanged(this);
  686. UpdateControls();
  687. object selected = tree.SelectedNode?.Tag;
  688. bool descrVisible = selected is MethodInfo || selected is SystemVariable;
  689. splitter.Visible = descrVisible;
  690. lblDescription.Visible = descrVisible;
  691. if (descrVisible)
  692. lblDescription.ShowDescription(report, selected);
  693. }
  694. private void tree_RightMouseButtonClicked(object sender, MouseEventArgs e)
  695. {
  696. mnuContext.Show(tree, e.Location);
  697. }
  698. private void tree_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e)
  699. {
  700. bool canEdit = (IsTable || IsEditableColumn || IsVariable || IsTotal) &&
  701. !Designer.Restrictions.DontEditData &&
  702. !(tree.SelectedNode.Tag as Base).HasRestriction(Restrictions.DontModify);
  703. if (!canEdit)
  704. e.CancelEdit = true;
  705. }
  706. private void tree_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
  707. {
  708. string newLabel = e.Label == null ? tree.SelectedNode.Text : e.Label;
  709. if (newLabel == tree.SelectedNode.Text)
  710. return;
  711. Base obj = tree.SelectedNode.Tag as Base;
  712. bool duplicateName = false;
  713. if (obj is DataSourceBase)
  714. {
  715. if (report.Dictionary.FindByAlias(newLabel) != null)
  716. duplicateName = true;
  717. else
  718. {
  719. (obj as DataSourceBase).Alias = newLabel;
  720. }
  721. }
  722. else if (obj is Column)
  723. {
  724. // get column name, take parent columns into account
  725. string columnName = newLabel;
  726. TreeNode node = tree.SelectedNode;
  727. while (true)
  728. {
  729. node = node.Parent;
  730. if (node.Tag is DataSourceBase)
  731. break;
  732. columnName = node.Text + "." + columnName;
  733. }
  734. DataSourceBase data = obj.Parent as DataSourceBase;
  735. if (data.Columns.FindByAlias(columnName) != null)
  736. duplicateName = true;
  737. else
  738. (obj as Column).Alias = columnName;
  739. }
  740. else if (obj is Parameter)
  741. {
  742. TreeNode parentNode = tree.SelectedNode.Parent;
  743. ParameterCollection parent = null;
  744. if (parentNode.Tag is Parameter)
  745. parent = (parentNode.Tag as Parameter).Parameters;
  746. else
  747. parent = report.Dictionary.Parameters;
  748. if (parent.FindByName(newLabel) != null)
  749. duplicateName = true;
  750. else
  751. obj.Name = newLabel;
  752. }
  753. else if (obj is Total)
  754. {
  755. if (report.Dictionary.FindByName(newLabel) != null)
  756. duplicateName = true;
  757. else
  758. obj.Name = newLabel;
  759. }
  760. if (duplicateName)
  761. {
  762. e.CancelEdit = true;
  763. FRMessageBox.Error(Res.Get("Designer,ToolWindow,Dictionary,DuplicateName"));
  764. }
  765. else
  766. Change();
  767. }
  768. private void tree_ItemDrag(object sender, ItemDragEventArgs e)
  769. {
  770. draggedItems.Clear();
  771. foreach (TreeNode n in tree.SelectedNodes)
  772. {
  773. string selectedItem = "";
  774. TreeNode node = n;
  775. if (node == null)
  776. continue;
  777. if (node.Tag is Column && !(node.Tag is DataSourceBase))
  778. {
  779. while (true)
  780. {
  781. if (node.Tag is DataSourceBase)
  782. {
  783. selectedItem = (node.Tag as DataSourceBase).FullName + "." + selectedItem;
  784. break;
  785. }
  786. selectedItem = node.Text + (selectedItem == "" ? "" : ".") + selectedItem;
  787. node = node.Parent;
  788. }
  789. }
  790. else if (node.Tag is Parameter || node.Tag is Total)
  791. {
  792. while (node != null && node.Tag != null)
  793. {
  794. if (node.Tag is Parameter || node.Tag is Total)
  795. selectedItem = node.Text + (selectedItem == "" ? "" : ".") + selectedItem;
  796. node = node.Parent;
  797. }
  798. }
  799. else if (node.Tag is MethodInfo)
  800. {
  801. MethodInfo info = node.Tag as MethodInfo;
  802. ParameterInfo[] pars = info.GetParameters();
  803. int parsLength = pars.Length;
  804. if (parsLength > 0 && pars[0].Name == "thisReport")
  805. parsLength--;
  806. selectedItem = info.Name + "(" + (parsLength > 1 ? "".PadRight(parsLength - 1, ',') : "") + ")";
  807. }
  808. if (selectedItem != "")
  809. draggedItems.Add(new DraggedItem(n.Tag, selectedItem));
  810. }
  811. if (draggedItems.Count > 0)
  812. tree.DoDragDrop(draggedItems, DragDropEffects.Move);
  813. else
  814. tree.DoDragDrop(e.Item, DragDropEffects.None);
  815. }
  816. private void tree_DragOver(object sender, DragEventArgs e)
  817. {
  818. dragIndicator.Hide();
  819. if (draggedItems.Count == 0)
  820. return;
  821. var pos = tree.PointToClient(new Point(e.X, e.Y));
  822. TreeNode targetNode = tree.GetNodeAt(pos);
  823. if (targetNode == null)
  824. return;
  825. object target = targetNode.Tag;
  826. // the only thing that can be dragged around the DictionaryWindow is a report parameter
  827. // allowed moves are:
  828. // - target is ParameterCollection: add node to collection or set its z-order to 0 if node is in collection already
  829. // - target is Parameter and dragged is not target and is not a root of target: reparent or change z-order (see notes below)
  830. // additional check is required against SystemVariable(s) because they are subclasses of Parameter/ParameterCollection
  831. if (target is SystemVariable || target is SystemVariables)
  832. return;
  833. int allow = 0;
  834. foreach (DraggedItem draggedItem in draggedItems)
  835. {
  836. object dragged = draggedItem.obj;
  837. if (dragged is Parameter dr && !(dragged is SystemVariable))
  838. {
  839. if (target is ParameterCollection ||
  840. (target is Parameter tr && target != dragged && !tr.HasParent(dr)))
  841. {
  842. allow++;
  843. }
  844. }
  845. }
  846. if (allow != 0 && allow == draggedItems.Count)
  847. {
  848. e.Effect = e.AllowedEffect;
  849. // check cursor position: less than 1/3 of target node width => change z-order, else change parent
  850. int _20 = Designer.LogicalToDevice(20);
  851. Rectangle dragRect = target is Parameter && pos.X < targetNode.Bounds.X + targetNode.Bounds.Width / 3 ?
  852. new Rectangle(_20, targetNode.Bounds.Top, tree.Width - _20 * 2, 0) :
  853. new Rectangle(targetNode.Bounds.Left, targetNode.Bounds.Bottom, targetNode.Bounds.Width, 0);
  854. dragIndicator.BackColor = tree.ForeColor;
  855. dragIndicator.SetBounds(tree.Left + dragRect.Left, tree.Top + dragRect.Top, dragRect.Width, Designer.LogicalToDevice(2));
  856. dragIndicator.Show();
  857. }
  858. }
  859. private void tree_DragDrop(object sender, DragEventArgs e)
  860. {
  861. dragIndicator.Hide();
  862. if (draggedItems.Count == 0)
  863. return;
  864. var pos = tree.PointToClient(new Point(e.X, e.Y));
  865. TreeNode targetNode = tree.GetNodeAt(pos);
  866. if (targetNode == null)
  867. return;
  868. object target = targetNode.Tag;
  869. if (target is SystemVariable || target is SystemVariables)
  870. return;
  871. string draggedName = "";
  872. foreach (DraggedItem draggedItem in draggedItems)
  873. {
  874. Parameter dragged = draggedItem.obj as Parameter;
  875. if (dragged == null || dragged is SystemVariable)
  876. continue;
  877. if (target is ParameterCollection collection)
  878. {
  879. if (collection.IndexOf(dragged) == -1)
  880. {
  881. FixParameterName(dragged, collection);
  882. collection.Add(dragged);
  883. }
  884. }
  885. else if (target is Parameter targetPar)
  886. {
  887. if (pos.X < targetNode.Bounds.X + targetNode.Bounds.Width / 3)
  888. {
  889. // insert dragged before target
  890. dragged.ParentCollection.Remove(dragged);
  891. var targetParentCollection = targetPar.ParentCollection;
  892. FixParameterName(dragged, targetParentCollection);
  893. targetParentCollection.Insert(targetParentCollection.IndexOf(targetPar), dragged);
  894. }
  895. else
  896. {
  897. if (targetPar.Parameters.IndexOf(dragged) == -1)
  898. {
  899. FixParameterName(dragged, targetPar.Parameters);
  900. dragged.Parent = targetPar;
  901. }
  902. }
  903. }
  904. draggedName = dragged.FullName;
  905. }
  906. // update all designer plugins (this one too)
  907. Designer.SetModified(null, "EditData");
  908. NavigateTo(Res.Get("Designer,ToolWindow,Dictionary,Parameters") + "." + draggedName);
  909. }
  910. private void tree_DragLeave(object sender, EventArgs e)
  911. {
  912. dragIndicator.Hide();
  913. }
  914. private void FixParameterName(Parameter p, ParameterCollection coll)
  915. {
  916. p.Name = coll.CreateUniqueName(p.Name);
  917. }
  918. #endregion
  919. #region Public Methods
  920. /// <inheritdoc/>
  921. public override void SelectionChanged()
  922. {
  923. base.SelectionChanged();
  924. if (Designer.SelectedObjects.Count == 0 || Designer.SelectedObjects[0] is ComponentBase)
  925. {
  926. updating = true;
  927. tree.SelectedNode = null;
  928. updating = false;
  929. UpdateControls();
  930. }
  931. }
  932. /// <inheritdoc/>
  933. public override void UpdateContent()
  934. {
  935. report = Designer.ActiveReport;
  936. Throttle.Execute(() =>
  937. {
  938. UpdateTree();
  939. // to save search results in DataTree when changing ReportTree
  940. #if !WPF
  941. SearchMatches();
  942. #endif
  943. });
  944. }
  945. /// <inheritdoc/>
  946. public override void Localize()
  947. {
  948. base.Localize();
  949. MyRes res = new MyRes("Designer,ToolWindow,Dictionary");
  950. Text = res.Get("");
  951. btnActions.Text = Res.Get("Buttons,Actions");
  952. btnEdit.ToolTipText = res.Get("Edit");
  953. btnDelete.ToolTipText = res.Get("Delete");
  954. btnView.ToolTipText = res.Get("View");
  955. miNew.Text = res.Get("New");
  956. miOpen.Text = res.Get("Open");
  957. miMerge.Text = res.Get("Merge");
  958. miSave.Text = res.Get("Save");
  959. miChooseData.Text = Res.Get("Designer,Menu,Data,Choose");
  960. miNewDataSource.Text = miNewDataSource1.Text = res.Get("NewDataSource");
  961. miSortDataSources.Text = miSortDataSources1.Text = res.Get("SortDataSources");
  962. miNewRelation.Text = res.Get("NewRelation");
  963. miNewParameter.Text = miNewParameter1.Text = res.Get("NewParameter");
  964. miNewTotal.Text = miNewTotal1.Text = res.Get("NewTotal");
  965. miNewCalculatedColumn.Text = miNewCalculatedColumn1.Text = res.Get("NewCalculatedColumn");
  966. miRename.Text = res.Get("Rename");
  967. miEdit.Text = res.Get("Edit");
  968. miDelete.Text = res.Get("Delete");
  969. miDeleteAlias.Text = res.Get("DeleteAlias");
  970. miView.Text = res.Get("View");
  971. miViewJson.Text = res.Get("ViewJson");
  972. miSortDataFields.Text = res.Get("SortDataFields");
  973. miCopyDataSource.Text = res.Get("CopyDataSource");
  974. miUploadDataSource.Text = miUploadDataSource1.Text = res.Get("UploadDataSource");
  975. UpdateTree();
  976. }
  977. /// <inheritdoc/>
  978. public override void UpdateUIStyle()
  979. {
  980. base.UpdateUIStyle();
  981. mnuContext.UpdateUIStyle();
  982. splitter.BackColor = UIStyleUtils.GetControlColor(Designer.UIStyle);
  983. }
  984. /// <inheritdoc/>
  985. public override void UpdateDpiDependencies()
  986. {
  987. base.UpdateDpiDependencies();
  988. Image = Designer.GetImage(72);
  989. tree.ImageList = mnuContext.ImageList = Designer.GetImages();
  990. mnuContext.Font = btnActions.Font = Designer.LogicalToDevice(DrawUtils.DefaultFont);
  991. btnActions.UpdateDpiDependencies(Designer);
  992. }
  993. /// <inheritdoc/>
  994. public override void SaveState()
  995. {
  996. base.SaveState();
  997. Storage.SetDip("DescriptionHeight", lblDescription.Height);
  998. }
  999. /// <inheritdoc/>
  1000. public override void RestoreState()
  1001. {
  1002. base.RestoreState();
  1003. lblDescription.Height = Storage.GetDip("DescriptionHeight", 50, 50, 200);
  1004. }
  1005. #endregion
  1006. /// <summary>
  1007. /// Initializes a new instance of the <see cref="DictionaryWindow"/> class with default settings.
  1008. /// </summary>
  1009. /// <param name="designer">The report designer.</param>
  1010. public DictionaryWindow(Designer designer)
  1011. : base(designer)
  1012. {
  1013. Name = "DictionaryWindow";
  1014. btnActions = new ToolbarDropDownButton("", -1, btnActions_DropDownOpening);
  1015. btnEdit = AddButton(68, miEdit_Click);
  1016. btnDelete = AddButton(51, miDelete_Click);
  1017. btnView = AddButton(54, miView_Click);
  1018. toolbar.Items.Insert(0, btnActions);
  1019. toolbar.Items.Insert(1, btnEdit);
  1020. toolbar.Items.Insert(2, btnDelete);
  1021. toolbar.Items.Insert(3, btnView);
  1022. miNew = AddMenuItem(0, miNew_Click);
  1023. miOpen = AddMenuItem(1, miOpen_Click);
  1024. miMerge = AddMenuItem(miMerge_Click);
  1025. miSave = AddMenuItem(2, miSave_Click);
  1026. miChooseData = AddMenuItem(Designer.cmdChooseData.Invoke);
  1027. miChooseData.BeginGroup = true;
  1028. miSortDataSources = AddMenuItem(Designer.cmdSortDataSources.Invoke);
  1029. miUploadDataSource = AddMenuItem(264, miUploadDataSource_Click);
  1030. miNewDataSource = AddMenuItem(137, Designer.cmdAddData.Invoke);
  1031. miNewDataSource.BeginGroup = true;
  1032. miNewRelation = AddMenuItem(139, miNewRelation_Click);
  1033. miNewCalculatedColumn = AddMenuItem(55, miNewCalculatedColumn_Click);
  1034. miNewParameter = AddMenuItem(56, miNewParameter_Click);
  1035. miNewTotal = AddMenuItem(65, miNewTotal_Click);
  1036. btnActions.AddDropDownItems(
  1037. miNew, miOpen, miMerge, miSave,
  1038. miChooseData, miSortDataSources,
  1039. #if !COMMUNITY
  1040. miUploadDataSource,
  1041. #endif
  1042. miNewDataSource, miNewRelation, miNewCalculatedColumn, miNewParameter, miNewTotal);
  1043. mnuContext = new ContextMenuBase(designer);
  1044. miSortDataSources1 = AddMenuItem(Designer.cmdSortDataSources.Invoke);
  1045. miUploadDataSource1 = AddMenuItem(206, miUploadDataSource_Click);
  1046. miNewDataSource1 = AddMenuItem(137, Designer.cmdAddData.Invoke);
  1047. miNewCalculatedColumn1 = AddMenuItem(55, miNewCalculatedColumn_Click);
  1048. miNewParameter1 = AddMenuItem(56, miNewParameter_Click);
  1049. miNewTotal1 = AddMenuItem(65, miNewTotal_Click);
  1050. miRename = AddMenuItem(miRename_Click);
  1051. //miRename.ShortcutKeys = Keys.F2;
  1052. miEdit = AddMenuItem(68, miEdit_Click);
  1053. miCopyDataSource = AddMenuItem(6, miCopyDataSource_Click);
  1054. miDelete = AddMenuItem(51, miDelete_Click);
  1055. miDeleteAlias = AddMenuItem(miDeleteAlias_Click);
  1056. miView = AddMenuItem(54, miView_Click);
  1057. miViewJson = AddMenuItem(54, miViewJson_Click);
  1058. miSortDataFields = AddMenuItem(miSortDataFields_Click);
  1059. mnuContext.Opening += mnuContext_Opening;
  1060. tree.AllowDrop = true;
  1061. tree.SelectionChanged += tree_SelectionChanged;
  1062. tree.RightMouseButtonClicked += tree_RightMouseButtonClicked;
  1063. tree.BeforeLabelEdit += tree_BeforeLabelEdit;
  1064. tree.AfterLabelEdit += tree_AfterLabelEdit;
  1065. tree.KeyDown += tree_KeyDown;
  1066. tree.DoubleClick += miEdit_Click;
  1067. tree.ItemDrag += tree_ItemDrag;
  1068. tree.DragOver += tree_DragOver;
  1069. tree.DragDrop += tree_DragDrop;
  1070. tree.DragLeave += tree_DragLeave;
  1071. dragIndicator = new Panel();
  1072. dragIndicator.Visible = false;
  1073. splitter = new Splitter();
  1074. splitter.Dock = DockStyle.Bottom;
  1075. splitter.Visible = false;
  1076. lblDescription = new DescriptionControl();
  1077. lblDescription.Dock = DockStyle.Bottom;
  1078. lblDescription.Height = 70;
  1079. lblDescription.Visible = false;
  1080. Controls.AddRange(new Control[] { dragIndicator, splitter, lblDescription });
  1081. Controls.SetChildIndex(dragIndicator, 0);
  1082. expandedNodes = new List<string>();
  1083. Localize();
  1084. UpdateDpiDependencies();
  1085. }
  1086. /// <summary>
  1087. /// Describes an item dragged from the "Data Dictionary" window.
  1088. /// </summary>
  1089. public class DraggedItem
  1090. {
  1091. /// <summary>
  1092. /// The dragged object.
  1093. /// </summary>
  1094. public Object obj;
  1095. /// <summary>
  1096. /// The text of dragged object.
  1097. /// </summary>
  1098. public string text;
  1099. internal DraggedItem(Object obj, string text)
  1100. {
  1101. this.obj = obj;
  1102. this.text = text;
  1103. }
  1104. }
  1105. /// <summary>
  1106. /// Collection of dragged items.
  1107. /// </summary>
  1108. public class DraggedItemCollection : List<DraggedItem>
  1109. {
  1110. internal DraggedItemCollection() : base() { }
  1111. }
  1112. internal static class DragUtils
  1113. {
  1114. public static DraggedItemCollection GetAll(DragEventArgs e)
  1115. {
  1116. // holding dragged objects data in DragEventArgs does not work in Mono. Use simpler way
  1117. //DraggedItemCollection items = (DraggedItemCollection)e.Data.GetData(typeof(DraggedItemCollection));
  1118. DraggedItemCollection items = DictionaryWindow.draggedItems;
  1119. if (items == null || items.Count == 0)
  1120. return null;
  1121. return items;
  1122. }
  1123. public static DraggedItem GetOne(DragEventArgs e)
  1124. {
  1125. DraggedItemCollection items = DictionaryWindow.draggedItems;
  1126. if (items == null || items.Count == 0)
  1127. return null;
  1128. return items[items.Count - 1];
  1129. }
  1130. }
  1131. }
  1132. }