KeywordsStringEditor.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. //
  5. // Purpose: Design-time editor for the strings that may contain
  6. // keywords. Form automatically retrives the list of
  7. // recongnizable keywords from the chart keywords
  8. // registry.
  9. //
  10. #if DESIGNER
  11. using System.Collections;
  12. using System.ComponentModel;
  13. using System.Diagnostics.CodeAnalysis;
  14. using System.Drawing;
  15. using System.Drawing.Design;
  16. using System.Globalization;
  17. using FastReport.DataVisualization.Charting;
  18. using FastReport.DataVisualization.Charting.Utilities;
  19. namespace FastReport.Design.DataVisualization.Charting
  20. {
  21. /// <summary>
  22. /// Stirng editor form that is used to edit properties that support keywords.
  23. /// </summary>
  24. internal class KeywordsStringEditorForm : System.Windows.Forms.Form
  25. {
  26. #region Fields
  27. // Form fields
  28. private System.Windows.Forms.RichTextBox _richTextBox;
  29. private System.Windows.Forms.GroupBox _groupBoxString;
  30. private System.Windows.Forms.Button _buttonOk;
  31. private System.Windows.Forms.Button _buttonCancel;
  32. private System.Windows.Forms.Button _buttonInsert;
  33. private System.Windows.Forms.Button _buttonEdit;
  34. private System.Windows.Forms.Label _labelDescription;
  35. private System.Windows.Forms.Panel _panelInsertEditButtons;
  36. private System.Windows.Forms.Panel _panelOkCancelButtons;
  37. private System.Windows.Forms.Panel _panelTopContent;
  38. /// <summary>
  39. /// Required designer variable.
  40. /// </summary>
  41. private System.ComponentModel.Container _components = null;
  42. /// <summary>
  43. /// Property name that is beign edited.
  44. /// </summary>
  45. private string _propertyName = string.Empty;
  46. /// <summary>
  47. /// Object/class name beign edited.
  48. /// </summary>
  49. private string _classTypeName = string.Empty;
  50. /// <summary>
  51. /// Initial string to be edited.
  52. /// </summary>
  53. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  54. private string _initialString = string.Empty;
  55. /// <summary>
  56. /// Result String after editing.
  57. /// </summary>
  58. public string ResultString = string.Empty;
  59. /// <summary>
  60. /// Maximum Y value index that can be used
  61. /// </summary>
  62. private int _maxYValueIndex = 9;
  63. /// <summary>
  64. /// List of applicable keywords
  65. /// </summary>
  66. internal ArrayList applicableKeywords = null;
  67. /// <summary>
  68. /// Reference to the keywords registry
  69. /// </summary>
  70. internal KeywordsRegistry KeywordsRegistry = null;
  71. /// <summary>
  72. /// Name of the last selected keyword name
  73. /// </summary>
  74. private string _selectedKeywordName = string.Empty;
  75. /// <summary>
  76. /// Start index of selected keyword.
  77. /// </summary>
  78. private int _selectedKeywordStart = -1;
  79. /// <summary>
  80. /// Length of selected keyword.
  81. /// </summary>
  82. private int _selectedKeywordLength = -1;
  83. /// <summary>
  84. /// Indicates that RTF control control is updating its text.
  85. /// Used to prevent recursive calls.
  86. /// </summary>
  87. private bool _updating = false;
  88. // resolved VSTS by extending the dialog by 36x28 pixels.
  89. // 5027 MultiLang: ChartAPI: Strings are truncated on the 'String Keywords Editor' dialog
  90. // 65162 Garbled characters in the String Keyword Editor on the designer
  91. // 16588 DEU and JPN: VCS/VB/VWD/VC: ChartAPI: Some string are truncated on the 'String Keywords Editor'
  92. // 3523 DEU and JPN: VCS/VB/VWD/VC: ChartAPI: Some string are truncated on the 'String Keywords Editor'
  93. private static int widthDialogExtend = 80;
  94. private static int heightDialogExtend = 38;
  95. #endregion // Fields
  96. #region Constructor
  97. /// <summary>
  98. /// Default public constructor
  99. /// </summary>
  100. public KeywordsStringEditorForm()
  101. {
  102. //
  103. // Required for Windows Form Designer support
  104. //
  105. InitializeComponent();
  106. PrepareControlsLayout();
  107. }
  108. /// <summary>
  109. /// Object constructor.
  110. /// </summary>
  111. /// <param name="initialString">String to edit.</param>
  112. /// <param name="classTypeName">Class name that beign edited.</param>
  113. /// <param name="propertyName">Property name that is beign edited.</param>
  114. /// <param name="maxYValueIndex">Maximum number of supported Y values.</param>
  115. public KeywordsStringEditorForm(string initialString, string classTypeName, string propertyName, int maxYValueIndex) : this()
  116. {
  117. // Save input parameters
  118. this._classTypeName = classTypeName;
  119. this._propertyName = propertyName;
  120. this._maxYValueIndex = maxYValueIndex;
  121. this._initialString = initialString;
  122. this.ResultString = initialString;
  123. }
  124. /// <summary>
  125. /// Clean up any resources being used.
  126. /// </summary>
  127. /// <param name="disposing">True if disposing.</param>
  128. protected override void Dispose( bool disposing )
  129. {
  130. if( disposing )
  131. {
  132. if(_components != null)
  133. {
  134. _components.Dispose();
  135. }
  136. }
  137. base.Dispose( disposing );
  138. }
  139. #endregion // Constructor
  140. #region Windows Form Designer generated code
  141. /// <summary>
  142. /// Required method for Designer support - do not modify
  143. /// the contents of this method with the code editor.
  144. /// </summary>
  145. private void InitializeComponent()
  146. {
  147. this._richTextBox = new System.Windows.Forms.RichTextBox();
  148. this._groupBoxString = new System.Windows.Forms.GroupBox();
  149. this._buttonEdit = new System.Windows.Forms.Button();
  150. this._buttonInsert = new System.Windows.Forms.Button();
  151. this._buttonOk = new System.Windows.Forms.Button();
  152. this._buttonCancel = new System.Windows.Forms.Button();
  153. this._labelDescription = new System.Windows.Forms.Label();
  154. this._panelOkCancelButtons = new System.Windows.Forms.Panel();
  155. this._panelTopContent = new System.Windows.Forms.Panel();
  156. this._panelInsertEditButtons = new System.Windows.Forms.Panel();
  157. this._groupBoxString.SuspendLayout();
  158. this._panelOkCancelButtons.SuspendLayout();
  159. this._panelTopContent.SuspendLayout();
  160. this._panelInsertEditButtons.SuspendLayout();
  161. this.SuspendLayout();
  162. //
  163. // richTextBox
  164. //
  165. this._richTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
  166. this._richTextBox.Location = new System.Drawing.Point(6, 19);
  167. this._richTextBox.Margin = new System.Windows.Forms.Padding(7);
  168. this._richTextBox.Name = "_richTextBox";
  169. this._richTextBox.Size = new System.Drawing.Size(488, 106);
  170. this._richTextBox.TabIndex = 0;
  171. this._richTextBox.WordWrap = false;
  172. this._richTextBox.SelectionChanged += new System.EventHandler(this.richTextBox_SelectionChanged);
  173. this._richTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.richTextBox_KeyDown);
  174. this._richTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.richTextBox_KeyPress);
  175. this._richTextBox.TextChanged += new System.EventHandler(this.richTextBox_TextChanged);
  176. //
  177. // groupBoxString
  178. //
  179. this._groupBoxString.Controls.Add(this._panelInsertEditButtons);
  180. this._groupBoxString.Controls.Add(this._richTextBox);
  181. this._groupBoxString.Dock = System.Windows.Forms.DockStyle.Fill;
  182. this._groupBoxString.Location = new System.Drawing.Point(0, 56);
  183. this._groupBoxString.Name = "_groupBoxString";
  184. this._groupBoxString.Padding = new System.Windows.Forms.Padding(6);
  185. this._groupBoxString.Size = new System.Drawing.Size(500, 131);
  186. this._groupBoxString.TabIndex = 1;
  187. this._groupBoxString.TabStop = false;
  188. this._groupBoxString.Text = SR.LabelStringWithKeywords;
  189. //
  190. // buttonEdit
  191. //
  192. this._buttonEdit.Enabled = false;
  193. this._buttonEdit.Location = new System.Drawing.Point(30, 34);
  194. this._buttonEdit.Name = "_buttonEdit";
  195. this._buttonEdit.Size = new System.Drawing.Size(156, 27);
  196. this._buttonEdit.TabIndex = 2;
  197. this._buttonEdit.Text = SR.LabelEditKeyword;
  198. this._buttonEdit.Click += new System.EventHandler(this.buttonEdit_Click);
  199. //
  200. // buttonInsert
  201. //
  202. this._buttonInsert.Location = new System.Drawing.Point(30, 2);
  203. this._buttonInsert.Name = "_buttonInsert";
  204. this._buttonInsert.Size = new System.Drawing.Size(156, 27);
  205. this._buttonInsert.TabIndex = 1;
  206. this._buttonInsert.Text = SR.LabelInsertNewKeyword;
  207. this._buttonInsert.Click += new System.EventHandler(this.buttonInsert_Click);
  208. //
  209. // buttonOk
  210. //
  211. this._buttonOk.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
  212. this._buttonOk.DialogResult = System.Windows.Forms.DialogResult.OK;
  213. this._buttonOk.Location = new System.Drawing.Point(305, 9);
  214. this._buttonOk.Name = "_buttonOk";
  215. this._buttonOk.Size = new System.Drawing.Size(90, 27);
  216. this._buttonOk.TabIndex = 2;
  217. this._buttonOk.Text = SR.LabelButtonOk;
  218. this._buttonOk.Click += new System.EventHandler(this.buttonOk_Click);
  219. //
  220. // buttonCancel
  221. //
  222. this._buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
  223. this._buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
  224. this._buttonCancel.Location = new System.Drawing.Point(401, 9);
  225. this._buttonCancel.Name = "_buttonCancel";
  226. this._buttonCancel.Size = new System.Drawing.Size(90, 27);
  227. this._buttonCancel.TabIndex = 3;
  228. this._buttonCancel.Text = SR.LabelButtonCancel;
  229. //
  230. // labelDescription
  231. //
  232. this._labelDescription.Dock = System.Windows.Forms.DockStyle.Top;
  233. this._labelDescription.Location = new System.Drawing.Point(0, 0);
  234. this._labelDescription.Name = "_labelDescription";
  235. this._labelDescription.Size = new System.Drawing.Size(500, 56);
  236. this._labelDescription.TabIndex = 0;
  237. this._labelDescription.Text = SR.DesciptionCustomLabelEditorTitle;
  238. //
  239. // _panelOkCancelButtons
  240. //
  241. this._panelOkCancelButtons.Controls.Add(this._buttonOk);
  242. this._panelOkCancelButtons.Controls.Add(this._buttonCancel);
  243. this._panelOkCancelButtons.Dock = System.Windows.Forms.DockStyle.Bottom;
  244. this._panelOkCancelButtons.Location = new System.Drawing.Point(4, 191);
  245. this._panelOkCancelButtons.Name = "_panelOkCancelButtons";
  246. this._panelOkCancelButtons.Padding = new System.Windows.Forms.Padding(6);
  247. this._panelOkCancelButtons.Size = new System.Drawing.Size(500, 44);
  248. this._panelOkCancelButtons.TabIndex = 4;
  249. //
  250. // _panelTopContent
  251. //
  252. this._panelTopContent.Controls.Add(this._groupBoxString);
  253. this._panelTopContent.Controls.Add(this._labelDescription);
  254. this._panelTopContent.Dock = System.Windows.Forms.DockStyle.Fill;
  255. this._panelTopContent.Location = new System.Drawing.Point(4, 4);
  256. this._panelTopContent.Name = "_panelTopContent";
  257. this._panelTopContent.Size = new System.Drawing.Size(500, 187);
  258. this._panelTopContent.TabIndex = 5;
  259. //
  260. // _panelInsertEditButtons
  261. //
  262. this._panelInsertEditButtons.Controls.Add(this._buttonInsert);
  263. this._panelInsertEditButtons.Controls.Add(this._buttonEdit);
  264. this._panelInsertEditButtons.Dock = System.Windows.Forms.DockStyle.Right;
  265. this._panelInsertEditButtons.Location = new System.Drawing.Point(305, 19);
  266. this._panelInsertEditButtons.Name = "_panelInsertEditButtons";
  267. this._panelInsertEditButtons.Size = new System.Drawing.Size(189, 106);
  268. this._panelInsertEditButtons.TabIndex = 3;
  269. //
  270. // KeywordsStringEditorForm
  271. //
  272. this.CancelButton = this._buttonCancel;
  273. this.ClientSize = new System.Drawing.Size(524, 275);
  274. this.Controls.Add(this._panelTopContent);
  275. this.Controls.Add(this._panelOkCancelButtons);
  276. this.MaximizeBox = false;
  277. this.MinimizeBox = false;
  278. this.MinimumSize = new System.Drawing.Size(524, 275);
  279. this.Padding = new System.Windows.Forms.Padding(4);
  280. this.ShowIcon = false;
  281. this.ShowInTaskbar = false;
  282. this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
  283. this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
  284. this.Name = "KeywordsStringEditorForm";
  285. this.Text = SR.LabelStringKeywordsEditor;
  286. this.Load += new System.EventHandler(this.KeywordsStringEditorForm_Load);
  287. this._groupBoxString.ResumeLayout(false);
  288. this._panelOkCancelButtons.ResumeLayout(false);
  289. this._panelTopContent.ResumeLayout(false);
  290. this._panelInsertEditButtons.ResumeLayout(false);
  291. this.ResumeLayout(false);
  292. }
  293. #endregion
  294. #region Event Handlers
  295. /// <summary>
  296. /// Form loaded event handler.
  297. /// </summary>
  298. /// <param name="sender">Event sender.</param>
  299. /// <param name="e">Event arguments.</param>
  300. private void KeywordsStringEditorForm_Load(object sender, System.EventArgs e)
  301. {
  302. // Insert new line characters in the text
  303. this._labelDescription.Text = this._labelDescription.Text.Replace("\\n", "\n");
  304. // Load list of keywords applicable for the specified object and property.
  305. this.applicableKeywords = this.GetApplicableKeywords();
  306. if(this.applicableKeywords.Count == 0)
  307. {
  308. this._buttonInsert.Enabled = false;
  309. this._buttonEdit.Enabled = false;
  310. }
  311. if (!String.IsNullOrEmpty(this._initialString))
  312. {
  313. // Set text to edit
  314. this._richTextBox.Rtf = this.GetRtfText(this._initialString);
  315. }
  316. }
  317. /// <summary>
  318. /// Insert keyword button clicked event handler.
  319. /// </summary>
  320. /// <param name="sender">Event sender.</param>
  321. /// <param name="e">Event arguments.</param>
  322. private void buttonInsert_Click(object sender, System.EventArgs e)
  323. {
  324. // Show keyword editor form
  325. KeywordEditor keywordEditor = new KeywordEditor(
  326. this.applicableKeywords,
  327. string.Empty,
  328. this._maxYValueIndex);
  329. if(keywordEditor.ShowDialog() == DialogResult.OK)
  330. {
  331. if(_selectedKeywordLength > 0)
  332. {
  333. // Insert keyword at the end of curently selected keyword
  334. // and separate them with space
  335. this._richTextBox.SelectionStart = this._richTextBox.SelectionStart + this._richTextBox.SelectionLength;
  336. this._richTextBox.SelectionLength = 0;
  337. this._richTextBox.SelectedText = " " + keywordEditor.Keyword;
  338. }
  339. else
  340. {
  341. // Insert new keyword at current location
  342. this._richTextBox.SelectionLength = Math.Max(0, this._selectedKeywordLength);
  343. this._richTextBox.SelectedText = keywordEditor.Keyword;
  344. }
  345. }
  346. // Set focus back to the editor
  347. this._richTextBox.Focus();
  348. }
  349. /// <summary>
  350. /// Edit keyword button clicked event handler.
  351. /// </summary>
  352. /// <param name="sender">Event sender.</param>
  353. /// <param name="e">Event arguments.</param>
  354. private void buttonEdit_Click(object sender, System.EventArgs e)
  355. {
  356. // Get seloected keyword
  357. string keyword = this._richTextBox.Text.Substring(this._selectedKeywordStart, this._selectedKeywordLength);
  358. // Show keyword editor form
  359. KeywordEditor keywordEditor = new KeywordEditor(
  360. this.applicableKeywords,
  361. keyword,
  362. this._maxYValueIndex);
  363. if(keywordEditor.ShowDialog() == DialogResult.OK)
  364. {
  365. int start = this._selectedKeywordStart;
  366. int length = this._selectedKeywordLength;
  367. // Update currently selected kyword
  368. this._richTextBox.Text = this._richTextBox.Text.Substring(0, start) +
  369. keywordEditor.Keyword +
  370. this._richTextBox.Text.Substring(start + length);
  371. this._richTextBox.SelectionStart = start + keywordEditor.Keyword.Length;
  372. }
  373. // Set focus back to the editor
  374. this._richTextBox.Focus();
  375. }
  376. /// <summary>
  377. /// Rich text box text changed event handler.
  378. /// </summary>
  379. /// <param name="sender">Event sender.</param>
  380. /// <param name="e">Event arguments.</param>
  381. private void richTextBox_TextChanged(object sender, System.EventArgs e)
  382. {
  383. if(!_updating)
  384. {
  385. _updating = true;
  386. // Save current selection
  387. int selectionStart = this._richTextBox.SelectionStart;
  388. int selectionLength = this._richTextBox.SelectionLength;
  389. // Update RTF tex
  390. _richTextBox.Rtf = this.GetRtfText(_richTextBox.Text);
  391. // Restore selection
  392. this._richTextBox.SelectionStart = selectionStart;
  393. this._richTextBox.SelectionLength = selectionLength;
  394. _updating = false;
  395. }
  396. }
  397. /// <summary>
  398. /// Rich text box selection changed event handler.
  399. /// </summary>
  400. /// <param name="sender">Event sender.</param>
  401. /// <param name="e">Event arguments.</param>
  402. private void richTextBox_SelectionChanged(object sender, System.EventArgs e)
  403. {
  404. // No any processing in selection mode with the Shift key down
  405. if((System.Windows.Forms.Control.ModifierKeys & Keys.Shift) != Keys.Shift)
  406. {
  407. if(!_updating)
  408. {
  409. _updating = true;
  410. // Update RTF text only when selected (bolded) keyword is changed
  411. string selectedKeywordTemp = this._selectedKeywordName;
  412. string newRtf = this.GetRtfText(_richTextBox.Text);
  413. if(selectedKeywordTemp != this._selectedKeywordName)
  414. {
  415. // Save current selection
  416. int selectionStart = this._richTextBox.SelectionStart;
  417. // Update RTF text
  418. _richTextBox.Rtf = newRtf;
  419. // Restore selection
  420. this._richTextBox.SelectionStart = selectionStart;
  421. this._richTextBox.SelectionLength = 0;
  422. }
  423. _updating = false;
  424. }
  425. }
  426. }
  427. /// <summary>
  428. /// Rich text box key pressed event handler.
  429. /// </summary>
  430. /// <param name="sender">Event sender.</param>
  431. /// <param name="e">Event arguments.</param>
  432. private void richTextBox_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
  433. {
  434. // Make sure we enter a closing bracket when user starts
  435. // entering the format string
  436. if(e.KeyChar == '{')
  437. {
  438. if(_richTextBox.SelectionColor == Color.Blue)
  439. {
  440. e.Handled = true;
  441. _richTextBox.SelectedText = "{}";
  442. _richTextBox.SelectionStart = _richTextBox.SelectionStart - 1;
  443. }
  444. }
  445. }
  446. /// <summary>
  447. /// Rich text box key down event handler.
  448. /// </summary>
  449. /// <param name="sender">Event sender.</param>
  450. /// <param name="e">Event arguments.</param>
  451. private void richTextBox_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
  452. {
  453. // Delete keyword when user press 'Delete' key
  454. if(e.KeyCode == Keys.Delete &&
  455. this._selectedKeywordStart >= 0 &&
  456. this._selectedKeywordLength > 0)
  457. {
  458. // Remember selection start because it will be changed as soon
  459. // as we update editor text
  460. int newSelectionPosition = this._selectedKeywordStart;
  461. // Remove keyword
  462. string newText = _richTextBox.Text.Substring(0, this._selectedKeywordStart);
  463. newText += _richTextBox.Text.Substring(this._selectedKeywordStart + this._selectedKeywordLength);
  464. _richTextBox.Text = newText;
  465. // Restore cursor (selection) position
  466. _richTextBox.SelectionStart = newSelectionPosition;
  467. e.Handled = true;
  468. }
  469. }
  470. /// <summary>
  471. /// Ok button pressed event handler.
  472. /// </summary>
  473. /// <param name="sender">Event sender.</param>
  474. /// <param name="e">Event arguments.</param>
  475. private void buttonOk_Click(object sender, System.EventArgs e)
  476. {
  477. // Get text from the editor
  478. this.ResultString = this._richTextBox.Text;
  479. // New line character should be presented as 2 characters "\n"
  480. this.ResultString = this.ResultString.Replace("\r\n", "\\n");
  481. this.ResultString = this.ResultString.Replace("\n", "\\n");
  482. }
  483. #endregion // Event Handlers
  484. #region Helper Methods
  485. /// <summary>
  486. /// Helper method that generates the RTF text based on the string.
  487. /// </summary>
  488. /// <param name="originalText">Input text.</param>
  489. /// <returns>Input text formatted as RTF.</returns>
  490. private string GetRtfText(string originalText)
  491. {
  492. // Initialize empty string
  493. string resultRtf = string.Empty;
  494. // Start with RTF header and font table
  495. resultRtf = @"{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 Microsoft Sans Serif;}}\r\n";
  496. // Add color table
  497. resultRtf += @"{\colortbl ;\red0\green0\blue255;}\r\n";
  498. // Add text starting tags
  499. resultRtf += @"\viewkind4\uc1\pard\f0\fs17 ";
  500. // Add text
  501. resultRtf += GetUnicodeRtf(this.GetColorHilightedRtfText(originalText));
  502. // Finish RTF format
  503. resultRtf += @"\par\r\n}";
  504. return resultRtf;
  505. }
  506. // VSTS: 65162: The non ansi 1252 characters will be lost, we need conversion in \uXXXX? format.
  507. private string GetUnicodeRtf(string orginalText)
  508. {
  509. System.Text.StringBuilder result = new System.Text.StringBuilder();
  510. foreach (char c in orginalText.ToCharArray())
  511. {
  512. int charInt = Convert.ToInt32(c);
  513. if (charInt < 0x00 || charInt > 0x7f)
  514. result.Append(@"\u" + charInt.ToString() + "?");
  515. else
  516. result.Append(Convert.ToString(c));
  517. }
  518. return result.ToString();
  519. }
  520. /// <summary>
  521. /// Gets specified text in RTF format where keyword are color highlighted.
  522. /// </summary>
  523. /// <param name="originalText">Original text.</param>
  524. /// <returns>Color higlighted RTF text.</returns>
  525. private string GetColorHilightedRtfText(string originalText)
  526. {
  527. string resultText = originalText;
  528. string selectedKeyword = string.Empty;
  529. // Reset selected keyword position
  530. this._selectedKeywordStart = -1;
  531. this._selectedKeywordLength = 0;
  532. // Current selection position that will be adjusted when formatting
  533. // characters are added infron of it.
  534. int selectionStart = this._richTextBox.SelectionStart;
  535. // Replace special new line character sequence "\n"
  536. resultText = resultText.Replace("\\n", "\r\n");
  537. // Replace special RTF Character '\'
  538. int slashCountre = 0;
  539. for(int index = 0; index < resultText.Length && index < selectionStart; index ++)
  540. {
  541. if(resultText[index] == '\\')
  542. {
  543. ++slashCountre;
  544. }
  545. }
  546. selectionStart += slashCountre;
  547. resultText = resultText.Replace(@"\", @"\\");
  548. // Iterate through all keywords
  549. foreach(KeywordInfo keywordInfo in this.applicableKeywords)
  550. {
  551. // Fill array of possible names for that keyword
  552. string[] keywordNames = keywordInfo.GetKeywords();
  553. // Iterate through all possible names
  554. foreach(string keywordNameWithSpaces in keywordNames)
  555. {
  556. int startIndex = 0;
  557. // Trim spaces
  558. string keywordName = keywordNameWithSpaces.Trim();
  559. // Skip empty strings
  560. if(keywordName.Length > 0)
  561. {
  562. // Try finding the keyword in the string
  563. while( (startIndex = resultText.IndexOf(keywordName, startIndex, StringComparison.Ordinal)) >= 0)
  564. {
  565. int keywordLength = keywordName.Length;
  566. // Check if Y value index can be part of the keyword
  567. if(keywordInfo.SupportsValueIndex)
  568. {
  569. if(resultText.Length > (startIndex + keywordLength) &&
  570. resultText[startIndex + keywordLength] == 'Y')
  571. {
  572. ++keywordLength;
  573. if(resultText.Length > (startIndex + keywordLength) &&
  574. char.IsDigit(resultText[startIndex + keywordLength]))
  575. {
  576. ++keywordLength;
  577. }
  578. }
  579. }
  580. // Check if format string can be part of the keyword
  581. if(keywordInfo.SupportsFormatting)
  582. {
  583. if(resultText.Length > (startIndex + keywordLength) &&
  584. resultText[startIndex + keywordLength] == '{')
  585. {
  586. ++keywordLength;
  587. int formatEndBracket = resultText.IndexOf("}", startIndex + keywordLength, StringComparison.Ordinal);
  588. if(formatEndBracket >= 0)
  589. {
  590. keywordLength += formatEndBracket - startIndex - keywordLength + 1;
  591. }
  592. }
  593. }
  594. // Check if cursor currently located inside the keyword
  595. bool isKeywordSelected = (selectionStart > (startIndex) &&
  596. selectionStart <= (startIndex + keywordLength) );
  597. // Show Keyword with different color
  598. string tempText = resultText.Substring(0, startIndex);
  599. string formattedKeyword = string.Empty;
  600. formattedKeyword += @"\cf1";
  601. if(isKeywordSelected)
  602. {
  603. // Remember selected keyword by name and position
  604. selectedKeyword = keywordInfo.Name;
  605. selectedKeyword += "__" + startIndex.ToString(CultureInfo.InvariantCulture);
  606. this._selectedKeywordStart = startIndex;
  607. this._selectedKeywordStart -= selectionStart - this._richTextBox.SelectionStart;
  608. this._selectedKeywordLength = keywordLength;
  609. formattedKeyword += @"\b";
  610. }
  611. formattedKeyword += @"\ul";
  612. // Replace keyword start symbol '#' with "#_" to avoid duplicate processing
  613. formattedKeyword += "#_";
  614. formattedKeyword += resultText.Substring(startIndex + 1, keywordLength - 1);
  615. formattedKeyword += @"\cf0";
  616. if(isKeywordSelected)
  617. {
  618. formattedKeyword += @"\b0";
  619. }
  620. formattedKeyword += @"\ul0 ";
  621. tempText += formattedKeyword;
  622. tempText += resultText.Substring(startIndex + keywordLength);
  623. resultText = tempText;
  624. // Adjust selection position
  625. if(startIndex < selectionStart)
  626. {
  627. selectionStart += formattedKeyword.Length - keywordLength;
  628. }
  629. // Increase search start index by the length of the keyword
  630. startIndex += formattedKeyword.Length;
  631. }
  632. }
  633. }
  634. }
  635. // Set currenly selected keyword name
  636. this._selectedKeywordName = selectedKeyword;
  637. // Update Edit button
  638. if(this._selectedKeywordName.Length > 0)
  639. {
  640. // Enable Edit button and set it text
  641. this._buttonEdit.Enabled = true;
  642. }
  643. else
  644. {
  645. this._buttonEdit.Enabled = false;
  646. }
  647. // Replace all the "\n" strings with new line objectTag "\par"
  648. resultText = resultText.Replace("\r\n", @"\par ");
  649. resultText = resultText.Replace("\n", @"\par ");
  650. resultText = resultText.Replace("\\n", @"\par ");
  651. // Replace special RTF Characters '{' and '}'
  652. // Has to be done after all processing because this character is
  653. // used in keywords formatting.
  654. resultText = resultText.Replace(@"{", @"\{");
  655. resultText = resultText.Replace(@"}", @"\}");
  656. // Replace the "#_" string with keyword start symbol.
  657. // This was previously chnaged to avoid duplicate processing.
  658. return resultText.Replace("#_", "#");
  659. }
  660. /// <summary>
  661. /// Get list of keywords applicable to current object and property.
  662. /// </summary>
  663. /// <returns></returns>
  664. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
  665. private ArrayList GetApplicableKeywords()
  666. {
  667. // Create new array
  668. ArrayList keywordList = new ArrayList();
  669. // Get acess to the chart keywords registry
  670. if(KeywordsRegistry != null &&
  671. this._propertyName.Length > 0 &&
  672. this._classTypeName.Length > 0)
  673. {
  674. // Iterate through all keywords in the registry
  675. foreach(KeywordInfo keywordInfo in KeywordsRegistry.registeredKeywords)
  676. {
  677. // Check if keyword is supported by specified type
  678. bool typeSupported = false;
  679. string[] typeNames = keywordInfo.AppliesToTypes.Split(',');
  680. foreach(string typeName in typeNames)
  681. {
  682. if(this._classTypeName == typeName.Trim())
  683. {
  684. typeSupported = true;
  685. break;
  686. }
  687. }
  688. // If type supported check property name
  689. if(typeSupported)
  690. {
  691. string[] propertyNames = keywordInfo.AppliesToProperties.Split(',');
  692. foreach(string propertyName in propertyNames)
  693. {
  694. if(this._propertyName == propertyName.Trim())
  695. {
  696. // Add KeywordInfo into the list
  697. keywordList.Add(keywordInfo);
  698. break;
  699. }
  700. }
  701. }
  702. }
  703. }
  704. return keywordList;
  705. }
  706. /// <summary>
  707. /// VSTS: 787930 - Expand the dialog with widthDialogExtend, heightDialogExtend to make room for localization.
  708. /// </summary>
  709. private void PrepareControlsLayout()
  710. {
  711. int buttonWidthAdd = 18;
  712. this.Width += widthDialogExtend;
  713. this._panelOkCancelButtons.Width += widthDialogExtend;
  714. this._panelInsertEditButtons.Width += widthDialogExtend;
  715. this._buttonInsert.Width += widthDialogExtend + buttonWidthAdd;
  716. this._buttonInsert.Left -= buttonWidthAdd;
  717. this._buttonEdit.Width += widthDialogExtend + buttonWidthAdd;
  718. this._buttonEdit.Left -= buttonWidthAdd;
  719. this._labelDescription.Width += widthDialogExtend;
  720. this.Height += heightDialogExtend;
  721. this._panelOkCancelButtons.Top += heightDialogExtend;
  722. this._labelDescription.Height += heightDialogExtend;
  723. }
  724. #endregion // Helper Methods
  725. }
  726. /// <summary>
  727. /// Editor for the string properties that may contain keyords.
  728. /// </summary>
  729. internal class KeywordsStringEditor : System.Drawing.Design.UITypeEditor
  730. {
  731. #region Editor methods and properties
  732. // Editor services
  733. private IWindowsFormsEditorService _edSvc = null;
  734. /// <summary>
  735. /// Edit label format by showing the form
  736. /// </summary>
  737. /// <param name="context">Editing context.</param>
  738. /// <param name="provider">Provider.</param>
  739. /// <param name="value">Value to edit.</param>
  740. /// <returns>Result</returns>
  741. [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily",
  742. Justification = "Too large of a code change to justify making this change")]
  743. public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
  744. {
  745. if (context != null &&
  746. context.Instance != null &&
  747. provider != null &&
  748. context.PropertyDescriptor != null)
  749. {
  750. _edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
  751. if (_edSvc != null)
  752. {
  753. // Try getting access to the associated series
  754. Series series = null;
  755. Chart chart = null;
  756. object instance = context.Instance;
  757. #if CHART_ACTLIST
  758. // Special processing if editor is called from the smart tag
  759. if (instance is ChartActionList)
  760. {
  761. chart = ((ChartActionList)instance).Chart;
  762. ChartActionList.SelectedItemInfo selectedItemInfo = ((ChartActionList)instance).GetSelectedItemInfo();
  763. if(selectedItemInfo != null)
  764. {
  765. instance = selectedItemInfo.SelectedObject;
  766. }
  767. }
  768. #endif //CHART_ACTLIST
  769. // Check object instance edited
  770. if(instance is Series)
  771. {
  772. series = (Series)instance;
  773. }
  774. else if(instance is DataPoint)
  775. {
  776. series = ((DataPoint)instance).series;
  777. }
  778. else if(instance is LegendItem)
  779. {
  780. if (((LegendItem)instance).Common != null)
  781. {
  782. chart = ((LegendItem)instance).Common.Chart;
  783. if (((LegendItem)instance).Common.DataManager.Series.IndexOf(((LegendItem)instance).SeriesName) >= 0)
  784. {
  785. series = ((LegendItem)instance).Common.DataManager.Series[((LegendItem)instance).SeriesName];
  786. }
  787. }
  788. }
  789. else if (instance is LegendCellColumn)
  790. {
  791. if (((LegendCellColumn)instance).Legend != null)
  792. {
  793. chart = ((LegendCellColumn)instance).Legend.Common.Chart;
  794. }
  795. }
  796. else if (instance is Annotation)
  797. {
  798. chart = ((Annotation)instance).Chart;
  799. if (((Annotation)instance).AnchorDataPoint != null)
  800. {
  801. series = ((Annotation)instance).AnchorDataPoint.series;
  802. }
  803. else if(chart != null && chart.Series.Count > 0)
  804. {
  805. series = chart.Series[0];
  806. }
  807. }
  808. // Make sure chart reference was found
  809. if(chart == null && series != null)
  810. {
  811. chart = series.Chart;
  812. }
  813. // Get maximum number of Y values
  814. int maxYValueNumber = 9;
  815. if(series != null)
  816. {
  817. maxYValueNumber = series.YValuesPerPoint - 1;
  818. }
  819. else if(chart != null)
  820. {
  821. // Find MAX number of Y values use in all series
  822. maxYValueNumber = 0;
  823. foreach(Series ser in chart.Series)
  824. {
  825. maxYValueNumber = Math.Max(maxYValueNumber, ser.YValuesPerPoint - 1);
  826. }
  827. }
  828. // Show editor form
  829. KeywordsStringEditorForm form = new KeywordsStringEditorForm(
  830. (string)value,
  831. instance.GetType().Name,
  832. context.PropertyDescriptor.Name,
  833. maxYValueNumber);
  834. if(chart != null)
  835. {
  836. form.KeywordsRegistry = (KeywordsRegistry)chart.GetService(typeof(KeywordsRegistry));
  837. }
  838. _edSvc.ShowDialog(form);
  839. value = form.ResultString;
  840. }
  841. }
  842. return value;
  843. }
  844. /// <summary>
  845. /// Show modal form.
  846. /// </summary>
  847. /// <param name="context">Editing context.</param>
  848. /// <returns>Editor style.</returns>
  849. public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
  850. {
  851. if (context != null && context.Instance != null)
  852. {
  853. return UITypeEditorEditStyle.Modal;
  854. }
  855. return base.GetEditStyle(context);
  856. }
  857. #endregion
  858. }
  859. }
  860. #endif