DataSeries.cs 69 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561
  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: Chart series collection class and series properties class.
  6. //
  7. using System;
  8. using System.Collections;
  9. using System.Collections.Generic;
  10. using System.ComponentModel;
  11. using System.Diagnostics.CodeAnalysis;
  12. using System.Drawing;
  13. using System.Drawing.Design;
  14. using System.Globalization;
  15. using FastReport.DataVisualization.Charting.ChartTypes;
  16. using FastReport.DataVisualization.Charting.Data;
  17. using FastReport.DataVisualization.Charting.Utilities;
  18. namespace FastReport.DataVisualization.Charting
  19. {
  20. #region Series enumerations
  21. /// <summary>
  22. /// Chart axis type (Primary or Secondary).
  23. /// </summary>
  24. public enum AxisType
  25. {
  26. /// <summary>
  27. /// Primary axis. For X axis - bottom, for Y axis - left.
  28. /// </summary>
  29. Primary,
  30. /// <summary>
  31. /// Secondary axis. For X axis - top, for Y axis - right.
  32. /// </summary>
  33. Secondary
  34. };
  35. /// <summary>
  36. /// Sorting order (Ascending or Descending).
  37. /// </summary>
  38. public enum PointSortOrder
  39. {
  40. /// <summary>
  41. /// Ascending sorting order
  42. /// </summary>
  43. Ascending,
  44. /// <summary>
  45. /// Descending sorting order
  46. /// </summary>
  47. Descending
  48. }
  49. #endregion
  50. /// <summary>
  51. /// Data series collection
  52. /// </summary>
  53. [
  54. SRDescription("DescriptionAttributeSeriesCollection_SeriesCollection"),
  55. ]
  56. public class SeriesCollection : ChartNamedElementCollection<Series>
  57. {
  58. #region Constructors
  59. /// <summary>
  60. /// Data series collection object constructor.
  61. /// </summary>
  62. internal SeriesCollection(DataManager dataManager)
  63. : base(dataManager)
  64. {
  65. }
  66. #endregion
  67. #region Methods
  68. /// <summary>
  69. /// Creates a new Series with the specified name and adds it to the collection.
  70. /// </summary>
  71. /// <param name="name">The new chart area name.</param>
  72. /// <returns>New series</returns>
  73. public Series Add(string name)
  74. {
  75. Series series = new Series(name);
  76. this.Add(series);
  77. return series;
  78. }
  79. /// <summary>
  80. /// Fixes the name references of the item.
  81. /// </summary>
  82. /// <param name="item">Item to verify and fix.</param>
  83. internal override void FixNameReferences(Series item)
  84. {
  85. if (item != null && Chart != null)
  86. {
  87. if (String.IsNullOrEmpty(item.ChartArea) && Chart.ChartAreas != null)
  88. {
  89. item.ChartArea = Chart.ChartAreas.DefaultNameReference;
  90. }
  91. if (String.IsNullOrEmpty(item.Legend) && Chart.Legends != null)
  92. {
  93. item.Legend = Chart.Legends.DefaultNameReference;
  94. }
  95. }
  96. }
  97. #endregion
  98. #region Event handlers
  99. /// <summary>
  100. /// Updates the Series' references to ChartAreas.
  101. /// </summary>
  102. /// <param name="sender">The sender.</param>
  103. /// <param name="e">The <see cref="Charting.NameReferenceChangedEventArgs"/> instance containing the event data.</param>
  104. internal void ChartAreaNameReferenceChanged(object sender, NameReferenceChangedEventArgs e)
  105. {
  106. foreach (Series series in this)
  107. if (series.ChartArea == e.OldName)
  108. series.ChartArea = e.NewName;
  109. }
  110. /// <summary>
  111. /// Updates the Series' references to Legends.
  112. /// </summary>
  113. /// <param name="sender">The sender.</param>
  114. /// <param name="e">The <see cref="Charting.NameReferenceChangedEventArgs"/> instance containing the event data.</param>
  115. internal void LegendNameReferenceChanged(object sender, NameReferenceChangedEventArgs e)
  116. {
  117. foreach (Series series in this)
  118. if (series.Legend == e.OldName)
  119. series.Legend = e.NewName;
  120. }
  121. #endregion
  122. }
  123. /// <summary>
  124. /// The class stores the data points and the default series properties.
  125. /// </summary>
  126. [
  127. SRDescription("DescriptionAttributeSeries_Series"),
  128. DefaultProperty("Points"),
  129. ]
  130. public class Series : DataPointCustomProperties
  131. {
  132. #region Fields
  133. // Private data members, which store properties values
  134. private ChartValueType _xValueType = ChartValueType.Auto;
  135. private ChartValueType _yValueType = ChartValueType.Auto;
  136. private bool _isXValueIndexed = false;
  137. private int _yValuesPerPoint = 1;
  138. private int _markersStep = 1;
  139. private ChartColorPalette _colorPalette = ChartColorPalette.None;
  140. private AxisType _xAxisType = AxisType.Primary;
  141. private AxisType _yAxisType = AxisType.Primary;
  142. #if SUBAXES
  143. private string _ySubAxisName = string.Empty;
  144. private string _xSubAxisName = string.Empty;
  145. #endif // SUBAXES
  146. private DataPointCustomProperties _emptyPointCustomProperties = null;
  147. private DataPointCollection _points;
  148. private int _shadowOffset = 0;
  149. private Color _shadowColor = Color.FromArgb(128, 0, 0, 0);
  150. private string _chartType = ChartTypeNames.Column;
  151. private string _chartArea = String.Empty;
  152. // Series enabled flag
  153. private bool _enabled = true;
  154. // Legend name used by this series
  155. private string _legend = String.Empty;
  156. // Member of the chart data source used to data bind to the X value of the series.
  157. private string _dataSourceXMember = String.Empty;
  158. // Members of the chart data source used to data bind to the Y values of the series.
  159. private string _dataSourceYMembers = String.Empty;
  160. // Automatic values type flags
  161. internal bool autoXValueType = false;
  162. internal bool autoYValueType = false;
  163. // Total Y value of all data points
  164. private double _totalYvalue = double.NaN;
  165. // Array of dummy data used at design time
  166. private double[] _dummyDoubleValues = null;
  167. // X value type if X value is indexed
  168. internal ChartValueType indexedXValueType = ChartValueType.Auto;
  169. // Default properties
  170. static internal DataPointCustomProperties defaultCustomProperties = InitializeDefaultCustomProperties();
  171. // Indicates that a temp. marker style was set for drawing
  172. internal bool tempMarkerStyleIsSet = false;
  173. // Indicates that number of Y values should be checked
  174. private bool _checkPointsNumber = true;
  175. // SmartLabelStyle style
  176. private SmartLabelStyle _smartLabelStyle = null;
  177. // Indicates that there is no custom axis labels in data points or series
  178. internal bool noLabelsInPoints = true;
  179. // Indicates if series has all X values set to 0
  180. internal bool xValuesZeros = false;
  181. // Indicates if check for series X zero values was done
  182. internal bool xValuesZerosChecked = false;
  183. // fake data points for selector service in design time.
  184. // note: in design time fake points are generated
  185. // with short life time - during painting.
  186. // this collection keep a copy of design time datapoints.
  187. internal DataPointCollection fakeDataPoints;
  188. #endregion
  189. #region Series properties fields
  190. /// <summary>
  191. /// Data point label text.
  192. /// </summary>
  193. internal string label = "";
  194. /// <summary>
  195. /// Data point X axis label text.
  196. /// </summary>
  197. internal string axisLabel = "";
  198. /// <summary>
  199. /// Data point label format string
  200. /// </summary>
  201. internal string labelFormat = "";
  202. /// <summary>
  203. /// If true shows point's value as a label.
  204. /// </summary>
  205. internal bool showLabelAsValue = false;
  206. /// <summary>
  207. /// Data point color
  208. /// </summary>
  209. internal Color color = Color.Empty;
  210. /// <summary>
  211. /// Data point border color
  212. /// </summary>
  213. internal Color borderColor = Color.Empty;
  214. /// <summary>
  215. /// Data point border style
  216. /// </summary>
  217. internal ChartDashStyle borderDashStyle = ChartDashStyle.Solid;
  218. /// <summary>
  219. /// Data point border width
  220. /// </summary>
  221. internal int borderWidth = 1;
  222. /// <summary>
  223. /// Data point marker border width
  224. /// </summary>
  225. internal int markerBorderWidth = 1;
  226. /// <summary>
  227. /// Data point background image
  228. /// </summary>
  229. internal string backImage = "";
  230. /// <summary>
  231. /// Data point background image drawing mode.
  232. /// </summary>
  233. internal ChartImageWrapMode backImageWrapMode = ChartImageWrapMode.Tile;
  234. /// <summary>
  235. /// Background image transparent color.
  236. /// </summary>
  237. internal Color backImageTransparentColor = Color.Empty;
  238. /// <summary>
  239. /// Background image alignment used by ClampUnscale drawing mode.
  240. /// </summary>
  241. internal ChartImageAlignmentStyle backImageAlignment = ChartImageAlignmentStyle.TopLeft;
  242. /// <summary>
  243. /// Data point background gradient type.
  244. /// </summary>
  245. internal GradientStyle backGradientStyle = GradientStyle.None;
  246. /// <summary>
  247. /// Data point background gradient end color
  248. /// </summary>
  249. internal Color backSecondaryColor = Color.Empty;
  250. /// <summary>
  251. /// Data point hatch style
  252. /// </summary>
  253. internal ChartHatchStyle backHatchStyle = ChartHatchStyle.None;
  254. /// <summary>
  255. /// Font cache for the fonts used in the Series and DataPoint
  256. /// </summary>
  257. private FontCache _fontCache = new FontCache();
  258. /// <summary>
  259. /// Data point font
  260. /// </summary>
  261. internal Font font = null;
  262. /// <summary>
  263. /// Data point line color
  264. /// </summary>
  265. internal Color fontColor = Color.Black;
  266. /// <summary>
  267. /// Data point font angle
  268. /// </summary>
  269. internal int fontAngle = 0;
  270. /// <summary>
  271. /// Data point marker style
  272. /// </summary>
  273. internal MarkerStyle markerStyle = MarkerStyle.None;
  274. /// <summary>
  275. /// Data point marker size
  276. /// </summary>
  277. internal int markerSize = 5;
  278. /// <summary>
  279. /// Data point marker image
  280. /// </summary>
  281. internal string markerImage = "";
  282. /// <summary>
  283. /// Data point marker image transparent color.
  284. /// </summary>
  285. internal Color markerImageTransparentColor = Color.Empty;
  286. /// <summary>
  287. /// Data point marker color
  288. /// </summary>
  289. internal Color markerColor = Color.Empty;
  290. /// <summary>
  291. /// Data point marker border color
  292. /// </summary>
  293. internal Color markerBorderColor = Color.Empty;
  294. /// <summary>
  295. /// The tooltip.
  296. /// </summary>
  297. internal string toolTip = "";
  298. /// <summary>
  299. /// Indicates that item is shown in the legend.
  300. /// </summary>
  301. internal bool showInLegend = true;
  302. /// <summary>
  303. /// Text of the item in the legend
  304. /// </summary>
  305. internal string legendText = "";
  306. /// <summary>
  307. /// Tooltip of the item in the legend
  308. /// </summary>
  309. internal string legendToolTip = "";
  310. /// <summary>
  311. /// Data point label back color
  312. /// </summary>
  313. internal Color labelBackColor = Color.Empty;
  314. /// <summary>
  315. /// Data point label border color
  316. /// </summary>
  317. internal Color labelBorderColor = Color.Empty;
  318. /// <summary>
  319. /// Data point label border style
  320. /// </summary>
  321. internal ChartDashStyle labelBorderDashStyle = ChartDashStyle.Solid;
  322. /// <summary>
  323. /// Data point label border width
  324. /// </summary>
  325. internal int labelBorderWidth = 1;
  326. /// <summary>
  327. /// Tooltip of the data point label
  328. /// </summary>
  329. internal string labelToolTip = "";
  330. #endregion
  331. #region Constructors and initialization
  332. /// <summary>
  333. /// Initializes the default custom properties field.
  334. /// </summary>
  335. /// <returns>A DataPointCustomProperties initialized to defaults</returns>
  336. private static DataPointCustomProperties InitializeDefaultCustomProperties()
  337. {
  338. DataPointCustomProperties customProperties = new DataPointCustomProperties(null, false);
  339. customProperties.SetDefault(true);
  340. customProperties.pointCustomProperties = true;
  341. return customProperties;
  342. }
  343. /// <summary>
  344. /// Series object constructor.
  345. /// </summary>
  346. public Series() : base(null, false)
  347. {
  348. InitProperties(null, 0);
  349. }
  350. /// <summary>
  351. /// Series object constructor.
  352. /// </summary>
  353. /// <param name="name">Name of the data series</param>
  354. public Series(string name) : base(null, false)
  355. {
  356. if(name == null)
  357. {
  358. throw (new ArgumentNullException(SR.ExceptionDataSeriesNameIsEmpty));
  359. }
  360. InitProperties(name, 0);
  361. }
  362. /// <summary>
  363. /// Series object constructor.
  364. /// </summary>
  365. /// <param name="name">Name of the data series.</param>
  366. /// <param name="yValues">Number of y values per data point.</param>
  367. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
  368. Justification = "Y is a cartesian coordinate and well understood")]
  369. public Series(string name, int yValues)
  370. : base(null, false)
  371. {
  372. if(name == null)
  373. {
  374. throw (new ArgumentNullException("name", SR.ExceptionDataSeriesNameIsEmpty));
  375. }
  376. if(YValuesPerPoint < 1)
  377. {
  378. throw (new ArgumentOutOfRangeException("yValues", SR.ExceptionDataSeriesYValuesPerPointIsZero));
  379. }
  380. InitProperties(name, yValues);
  381. }
  382. /// <summary>
  383. /// Initialize series properties
  384. /// </summary>
  385. private void InitProperties(string name, int YValuesPerPoint)
  386. {
  387. this.font = _fontCache.DefaultFont;
  388. this.series = this;
  389. this._emptyPointCustomProperties = new DataPointCustomProperties(this, false);
  390. this._emptyPointCustomProperties.series = this;
  391. // Initialize properties
  392. _points = new DataPointCollection(this);
  393. fakeDataPoints = new DataPointCollection(this);
  394. if(name != null)
  395. {
  396. base.Name = name;
  397. }
  398. if(YValuesPerPoint != 0)
  399. {
  400. _yValuesPerPoint = YValuesPerPoint;
  401. }
  402. base.SetDefault(true);
  403. _emptyPointCustomProperties.SetDefault(true);
  404. _emptyPointCustomProperties.pointCustomProperties = true;
  405. //TODO : check if this is still needed.
  406. //#if !SQLRS_CONTROL
  407. // // Use transparent colors for empty points
  408. // emptyPointAttributes.Color = Color.Transparent;
  409. // emptyPointAttributes.BorderColor = Color.Transparent;
  410. // emptyPointAttributes.FontColor = Color.Transparent;
  411. // emptyPointAttributes.MarkerColor = Color.Transparent;
  412. // emptyPointAttributes.MarkerBorderColor = Color.Transparent;
  413. //#endif //!SQLRS_CONTROL
  414. // Create SmartLabelStyle style object
  415. _smartLabelStyle = new SmartLabelStyle(this);
  416. }
  417. #endregion
  418. #region Helper methods
  419. /// <summary>
  420. /// Gets series caption that may not be the same as series name.
  421. /// </summary>
  422. /// <returns>Series caption string.</returns>
  423. internal string GetCaption()
  424. {
  425. if (this.IsCustomPropertySet("SeriesCaption"))
  426. {
  427. return this["SeriesCaption"];
  428. }
  429. return this.Name;
  430. }
  431. /// <summary>
  432. /// Gets custom points depth and gap depth from series properties.
  433. /// </summary>
  434. /// <param name="graph">Chart graphics.</param>
  435. /// <param name="axis">Categorical axis.</param>
  436. /// <param name="pointDepth">Returns point depth.</param>
  437. /// <param name="pointGapDepth">Return point gap depth.</param>
  438. internal void GetPointDepthAndGap(
  439. ChartGraphics graph,
  440. Axis axis,
  441. ref double pointDepth,
  442. ref double pointGapDepth)
  443. {
  444. // Check if series provide custom value for point depth in pixels
  445. string attribValue = this[CustomPropertyName.PixelPointDepth];
  446. if(attribValue != null)
  447. {
  448. try
  449. {
  450. pointDepth = CommonElements.ParseDouble(attribValue);
  451. }
  452. catch
  453. {
  454. throw (new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid2("PixelPointDepth")));
  455. }
  456. if (pointDepth <= 0)
  457. {
  458. throw (new InvalidOperationException(SR.ExceptionCustomAttributeIsNotLargerThenZiro("PixelPointDepth")));
  459. }
  460. if (pointDepth > CustomPropertyRegistry.MaxValueOfPixelAttribute)
  461. {
  462. throw (new InvalidOperationException(SR.ExceptionCustomAttributeMustBeInRange("PixelPointDepth", (0).ToString(CultureInfo.CurrentCulture), CustomPropertyRegistry.MaxValueOfPixelAttribute.ToString(CultureInfo.CurrentCulture))));
  463. }
  464. SizeF relativeSize = graph.GetRelativeSize(new SizeF((float)pointDepth, (float)pointDepth));
  465. pointDepth = relativeSize.Width;
  466. if(axis.AxisPosition == AxisPosition.Left || axis.AxisPosition == AxisPosition.Right)
  467. {
  468. pointDepth = relativeSize.Height;
  469. }
  470. }
  471. // Check if series provide custom value for point gap depth in pixels
  472. attribValue = this[CustomPropertyName.PixelPointGapDepth];
  473. if(attribValue != null)
  474. {
  475. try
  476. {
  477. pointGapDepth = CommonElements.ParseDouble(attribValue);
  478. }
  479. catch
  480. {
  481. throw (new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid2("PixelPointGapDepth")));
  482. }
  483. if (pointGapDepth <= 0)
  484. {
  485. throw (new InvalidOperationException(SR.ExceptionCustomAttributeIsNotLargerThenZiro("PixelPointGapDepth")));
  486. }
  487. if (pointGapDepth > CustomPropertyRegistry.MaxValueOfPixelAttribute)
  488. {
  489. throw (new InvalidOperationException(SR.ExceptionCustomAttributeMustBeInRange("PixelPointGapDepth", (0).ToString(CultureInfo.CurrentCulture), CustomPropertyRegistry.MaxValueOfPixelAttribute.ToString(CultureInfo.CurrentCulture))));
  490. }
  491. SizeF relativeSize = graph.GetRelativeSize(new SizeF((float)pointGapDepth, (float)pointGapDepth));
  492. pointGapDepth = relativeSize.Width;
  493. if(axis.AxisPosition == AxisPosition.Left || axis.AxisPosition == AxisPosition.Right)
  494. {
  495. pointGapDepth = relativeSize.Height;
  496. }
  497. }
  498. }
  499. /// <summary>
  500. /// Gets data point width in relative coordinates.
  501. /// </summary>
  502. /// <param name="graph">Chart graphics.</param>
  503. /// <param name="axis">Axis object.</param>
  504. /// <param name="interval">Current minimum axis interval.</param>
  505. /// <param name="defaultWidth">Default width in percentage of interval.</param>
  506. /// <returns>Point width.</returns>
  507. internal double GetPointWidth(
  508. ChartGraphics graph,
  509. Axis axis,
  510. double interval,
  511. double defaultWidth)
  512. {
  513. double pointPercentageWidth = defaultWidth;
  514. double pointWidth = 0.0;
  515. // Check if series provide custom value for point width in percentage of interval
  516. string strWidth = this[CustomPropertyName.PointWidth];
  517. if(strWidth != null)
  518. {
  519. pointPercentageWidth = CommonElements.ParseDouble(strWidth);
  520. }
  521. // Get column width in relative and pixel coordinates
  522. pointWidth = axis.GetPixelInterval( interval * pointPercentageWidth );
  523. SizeF pointSize = graph.GetAbsoluteSize(new SizeF((float)pointWidth, (float)pointWidth));
  524. double pixelPointWidth = pointSize.Width;
  525. if(axis.AxisPosition == AxisPosition.Left || axis.AxisPosition == AxisPosition.Right)
  526. {
  527. pixelPointWidth = pointSize.Height;
  528. }
  529. // Check if series provide custom value for Min point width in pixels
  530. bool usePixelWidth = false;
  531. string attribValue = this[CustomPropertyName.MinPixelPointWidth];
  532. if(attribValue != null)
  533. {
  534. double minPixelPointWidth = 0.0;
  535. try
  536. {
  537. minPixelPointWidth = CommonElements.ParseDouble(attribValue);
  538. }
  539. catch
  540. {
  541. throw(new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid2("MinPixelPointWidth")));
  542. }
  543. if(minPixelPointWidth <= 0.0)
  544. {
  545. throw(new InvalidOperationException(SR.ExceptionCustomAttributeIsNotLargerThenZiro("MinPixelPointWidth")));
  546. }
  547. if (minPixelPointWidth > CustomPropertyRegistry.MaxValueOfPixelAttribute)
  548. {
  549. throw (new InvalidOperationException(SR.ExceptionCustomAttributeMustBeInRange("MinPixelPointWidth", (0).ToString(CultureInfo.CurrentCulture), CustomPropertyRegistry.MaxValueOfPixelAttribute.ToString(CultureInfo.CurrentCulture))));
  550. }
  551. if(pixelPointWidth < minPixelPointWidth)
  552. {
  553. usePixelWidth = true;
  554. pixelPointWidth = minPixelPointWidth;
  555. }
  556. }
  557. // Check if series provide custom value for Max point width in pixels
  558. attribValue = this[CustomPropertyName.MaxPixelPointWidth];
  559. if(attribValue != null)
  560. {
  561. double maxPixelPointWidth = 0.0;
  562. try
  563. {
  564. maxPixelPointWidth = CommonElements.ParseDouble(attribValue);
  565. }
  566. catch
  567. {
  568. throw(new InvalidOperationException( SR.ExceptionCustomAttributeValueInvalid2("MaxPixelPointWidth")));
  569. }
  570. if(maxPixelPointWidth <= 0)
  571. {
  572. throw(new InvalidOperationException(SR.ExceptionCustomAttributeIsNotLargerThenZiro("MaxPixelPointWidth")));
  573. }
  574. if(pixelPointWidth > maxPixelPointWidth)
  575. {
  576. usePixelWidth = true;
  577. pixelPointWidth = maxPixelPointWidth;
  578. }
  579. }
  580. // Check if series provide custom value for point width in pixels
  581. attribValue = this[CustomPropertyName.PixelPointWidth];
  582. if(attribValue != null)
  583. {
  584. usePixelWidth = true;
  585. pixelPointWidth = 0.0;
  586. try
  587. {
  588. pixelPointWidth = CommonElements.ParseDouble(attribValue);
  589. }
  590. catch
  591. {
  592. throw(new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid2("PixelPointWidth")));
  593. }
  594. if(pixelPointWidth <= 0)
  595. {
  596. throw(new InvalidOperationException(SR.ExceptionCustomAttributeIsNotLargerThenZiro("PixelPointWidth")));
  597. }
  598. if (pixelPointWidth > CustomPropertyRegistry.MaxValueOfPixelAttribute)
  599. {
  600. throw (new InvalidOperationException(SR.ExceptionCustomAttributeMustBeInRange("PixelPointWidth", (0).ToString(CultureInfo.CurrentCulture), CustomPropertyRegistry.MaxValueOfPixelAttribute.ToString(CultureInfo.CurrentCulture))));
  601. }
  602. }
  603. // Translate pixel width to relative coordinates
  604. if(usePixelWidth)
  605. {
  606. SizeF pointRelativeSize = graph.GetRelativeSize(new SizeF((float)pixelPointWidth, (float)pixelPointWidth));
  607. pointWidth = pointRelativeSize.Width;
  608. if(axis.AxisPosition == AxisPosition.Left || axis.AxisPosition == AxisPosition.Right)
  609. {
  610. pointWidth = pointRelativeSize.Height;
  611. }
  612. }
  613. return pointWidth;
  614. }
  615. /// <summary>
  616. /// Get chart type name by it's type
  617. /// </summary>
  618. /// <param name="type">Chart type.</param>
  619. /// <returns>Chart type name.</returns>
  620. static internal string GetChartTypeName(SeriesChartType type)
  621. {
  622. if(type == SeriesChartType.StackedArea100)
  623. return ChartTypeNames.OneHundredPercentStackedArea;
  624. if(type == SeriesChartType.StackedBar100)
  625. return ChartTypeNames.OneHundredPercentStackedBar;
  626. if(type == SeriesChartType.StackedColumn100)
  627. return ChartTypeNames.OneHundredPercentStackedColumn;
  628. return Enum.GetName(typeof(SeriesChartType), type);
  629. }
  630. /// <summary>
  631. /// Checks if Y values of the series represent date-time.
  632. /// </summary>
  633. /// <returns>True if date-time.</returns>
  634. internal bool IsYValueDateTime()
  635. {
  636. if(this.YValueType == ChartValueType.Date ||
  637. this.YValueType == ChartValueType.DateTime ||
  638. this.YValueType == ChartValueType.Time ||
  639. this.YValueType == ChartValueType.DateTimeOffset)
  640. {
  641. return true;
  642. }
  643. return false;
  644. }
  645. /// <summary>
  646. /// Checks if X values of the series represent date-time.
  647. /// </summary>
  648. /// <returns>True if date-time.</returns>
  649. internal bool IsXValueDateTime()
  650. {
  651. if(this.XValueType == ChartValueType.Date ||
  652. this.XValueType == ChartValueType.DateTime ||
  653. this.XValueType == ChartValueType.Time ||
  654. this.XValueType == ChartValueType.DateTimeOffset)
  655. {
  656. return true;
  657. }
  658. return false;
  659. }
  660. /// <summary>
  661. /// Checks if series is visible.
  662. /// </summary>
  663. /// <returns>True if series is visible.</returns>
  664. internal bool IsVisible()
  665. {
  666. // Check if enabled flag is set and the ChartArea is defined
  667. if(this.Enabled && !String.IsNullOrEmpty(this.ChartArea))
  668. {
  669. return true;
  670. }
  671. return false;
  672. }
  673. /// <summary>
  674. /// Checks if series chart type uses a "Fast" mode chart type.
  675. /// </summary>
  676. /// <returns>True if series uses "Fast" mode chart type.</returns>
  677. internal bool IsFastChartType()
  678. {
  679. // Check if fast mode chart type is used in the series
  680. if(this.ChartType == SeriesChartType.FastLine)
  681. {
  682. return true;
  683. }
  684. // Check if fast mode chart type is used in the series
  685. if(this.ChartType == SeriesChartType.FastPoint)
  686. {
  687. return true;
  688. }
  689. return false;
  690. }
  691. /// <summary>
  692. /// Throws exception if specified value type is not supported.
  693. /// </summary>
  694. /// <param name="type">Value type to check.</param>
  695. internal void CheckSupportedTypes(Type type)
  696. {
  697. // Check parameters type
  698. if(type == typeof(Double) ||
  699. type == typeof(DateTime) ||
  700. type == typeof(String) ||
  701. type == typeof(Int32) ||
  702. type == typeof(UInt32) ||
  703. type == typeof(Decimal) ||
  704. type == typeof(Single) ||
  705. type == typeof(Int16) ||
  706. type == typeof(UInt16) ||
  707. type == typeof(Int64) ||
  708. type == typeof(UInt64) ||
  709. type == typeof(Byte) ||
  710. type == typeof(SByte) ||
  711. type == typeof(System.DBNull) ||
  712. type == typeof(Boolean) )
  713. {
  714. return;
  715. }
  716. // Unsupported parameter type
  717. throw(new ArgumentException(SR.ExceptionDataSeriesPointTypeUnsupported( type.ToString() ) ));
  718. }
  719. /// <summary>
  720. /// Apply palette colors to the data series points if UsePaletteColors property is set.
  721. /// </summary>
  722. internal void ApplyPaletteColors()
  723. {
  724. // Use Series or Data Manager palette
  725. DataManager dataManager = this.Common.DataManager;
  726. ChartColorPalette currentPalette = (this.Palette == ChartColorPalette.None) ?
  727. dataManager.Palette : this.Palette;
  728. // if it is still none - check if custom colors pallete is empty.
  729. if (
  730. currentPalette == ChartColorPalette.None &&
  731. dataManager.PaletteCustomColors.Length == 0
  732. )
  733. {
  734. currentPalette = ChartColorPalette.BrightPastel;
  735. }
  736. // Get palette colors
  737. int colorIndex = 0;
  738. Color[] paletteColors = (currentPalette == ChartColorPalette.None) ?
  739. dataManager.PaletteCustomColors : ChartPaletteColors.GetPaletteColors(currentPalette);
  740. foreach(DataPoint dataPoint in _points)
  741. {
  742. // Change color of the series data points only if no color is set
  743. if((!dataPoint.IsCustomPropertySet(CommonCustomProperties.Color) || dataPoint.tempColorIsSet ) && !dataPoint.IsEmpty)
  744. {
  745. dataPoint.SetAttributeObject(CommonCustomProperties.Color, paletteColors[colorIndex]);
  746. dataPoint.tempColorIsSet = true;
  747. ++colorIndex;
  748. if(colorIndex >= paletteColors.Length)
  749. {
  750. colorIndex = 0;
  751. }
  752. }
  753. }
  754. }
  755. /// <summary>
  756. /// Gets design time dummy data.
  757. /// </summary>
  758. /// <param name="type">AxisName of the data to get.</param>
  759. /// <returns>Dummy data for chart in design-time.</returns>
  760. internal IEnumerable GetDummyData(ChartValueType type)
  761. {
  762. string[] stringValues = { "abc1", "abc2", "abc3", "abc4", "abc5", "abc6" };
  763. DateTime[] dateValues = { DateTime.Now.Date, DateTime.Now.Date.AddDays(1), DateTime.Now.Date.AddDays(2), DateTime.Now.Date.AddDays(3), DateTime.Now.Date.AddDays(4), DateTime.Now.Date.AddDays(4) };
  764. // Fill array of random data
  765. if(_dummyDoubleValues == null)
  766. {
  767. //TODO: Check, what is needed from here...
  768. //#if !SQLRS_CONTROL
  769. // Random random2 = new Random(unchecked((int)DateTime.Now.Ticks +
  770. // this.Color.B + this.Color.G + this.Color.R));
  771. //#else
  772. int seed = 0;
  773. for (int index = 0; index < this.Name.Length; index++)
  774. seed += (int)this.Name[index];
  775. Random random2 = new Random(seed);
  776. //#endif
  777. _dummyDoubleValues = new double[6];
  778. for(int valueIndex = 0; valueIndex < 6; valueIndex++)
  779. {
  780. _dummyDoubleValues[valueIndex] = random2.Next(10, 100);
  781. }
  782. }
  783. // Return dummy data
  784. if(type == ChartValueType.DateTime || type == ChartValueType.Date || type == ChartValueType.DateTimeOffset)
  785. {
  786. return dateValues;
  787. }
  788. else if(type == ChartValueType.Time)
  789. {
  790. dateValues = new DateTime[] { DateTime.Now, DateTime.Now.AddMinutes(1), DateTime.Now.AddMinutes(2), DateTime.Now.AddMinutes(3), DateTime.Now.AddMinutes(4), DateTime.Now.AddMinutes(4) };
  791. return dateValues;
  792. }
  793. else if(type == ChartValueType.String)
  794. {
  795. return stringValues;
  796. }
  797. return _dummyDoubleValues;
  798. }
  799. /// <summary>
  800. /// Returns total of the Y values.
  801. /// </summary>
  802. /// <returns>Y values total.</returns>
  803. internal double GetTotalYValue()
  804. {
  805. return this.GetTotalYValue(0);
  806. }
  807. /// <summary>
  808. /// Returns total of the Y values.
  809. /// </summary>
  810. /// <param name="yValueIndex">Index of the Y value to use</param>
  811. /// <returns>Y values total.</returns>
  812. internal double GetTotalYValue(int yValueIndex)
  813. {
  814. if(yValueIndex == 0)
  815. {
  816. // Total was already calculated
  817. if(!double.IsNaN(_totalYvalue))
  818. {
  819. return _totalYvalue;
  820. }
  821. // Calculate total
  822. _totalYvalue = 0;
  823. foreach(DataPoint point in this.Points)
  824. {
  825. _totalYvalue += point.YValues[yValueIndex];
  826. }
  827. return _totalYvalue;
  828. }
  829. // Check if series has enough Y values
  830. if(yValueIndex >= this.YValuesPerPoint)
  831. {
  832. throw(new InvalidOperationException( SR.ExceptionDataSeriesYValueIndexNotExists(yValueIndex.ToString(CultureInfo.InvariantCulture), this.Name ) ) );
  833. }
  834. // Calculate total
  835. double yValue = 0;
  836. foreach(DataPoint point in this.Points)
  837. {
  838. yValue += point.YValues[yValueIndex];
  839. }
  840. return yValue;
  841. }
  842. /// <summary>
  843. /// Replaces predefined keyword inside the string with their values.
  844. /// </summary>
  845. /// <param name="strOriginal">Original string with keywords.</param>
  846. /// <returns>Modified string.</returns>
  847. internal override string ReplaceKeywords(string strOriginal)
  848. {
  849. // Nothing to process
  850. if(strOriginal == null || strOriginal.Length == 0)
  851. return strOriginal;
  852. // Replace all "\n" strings with '\n' character
  853. string result = strOriginal.Replace("\\n", "\n");
  854. // #SERIESNAME - series name
  855. result = result.Replace(KeywordName.SeriesName, this.Name);
  856. result = result.Replace(KeywordName.Ser, this.Name); // #SER Depricated Keyword
  857. // #CUSTOMPROPERTY - one of the custom attributes by name
  858. result = DataPoint.ReplaceCustomPropertyKeyword(result, this);
  859. // #TOTAL - total of Y values
  860. result = ReplaceOneKeyword(
  861. this.Chart,
  862. this,
  863. this.Tag,
  864. ChartElementType.Nothing,
  865. result,
  866. KeywordName.Total,
  867. SeriesValuesFormulaType.Total,
  868. this.YValueType,
  869. "");
  870. // #AVG - total of Y values
  871. result = ReplaceOneKeyword(
  872. this.Chart,
  873. this,
  874. this.Tag,
  875. ChartElementType.Nothing,
  876. result,
  877. KeywordName.Avg,
  878. SeriesValuesFormulaType.Average,
  879. this.YValueType,
  880. "");
  881. // #MAX - total of Y values
  882. result = ReplaceOneKeyword(
  883. this.Chart,
  884. this,
  885. this.Tag,
  886. ChartElementType.Nothing,
  887. result,
  888. KeywordName.Max,
  889. SeriesValuesFormulaType.Maximum,
  890. this.YValueType,
  891. "");
  892. // #MIN - total of Y values
  893. result = ReplaceOneKeyword(
  894. this.Chart,
  895. this,
  896. this.Tag,
  897. ChartElementType.Nothing,
  898. result,
  899. KeywordName.Min,
  900. SeriesValuesFormulaType.Minimum,
  901. this.YValueType,
  902. "");
  903. // #FIRST - total of Y values
  904. result = ReplaceOneKeyword(
  905. this.Chart,
  906. this,
  907. this.Tag,
  908. ChartElementType.Nothing,
  909. result,
  910. KeywordName.First,
  911. SeriesValuesFormulaType.First,
  912. this.YValueType,
  913. "");
  914. // #LAST - total of Y values
  915. result = ReplaceOneKeyword(
  916. this.Chart,
  917. this,
  918. this.Tag,
  919. ChartElementType.Nothing,
  920. result,
  921. KeywordName.Last,
  922. SeriesValuesFormulaType.Last,
  923. this.YValueType,
  924. "");
  925. // #LEGENDTEXT - series name
  926. result = result.Replace(KeywordName.LegendText, this.LegendText);
  927. return result;
  928. }
  929. /// <summary>
  930. /// Helper function which replaces one keyword.
  931. /// </summary>
  932. /// <param name="chart">Chart object reference.</param>
  933. /// <param name="elementType">Chart element type.</param>
  934. /// <param name="obj">Object being formatted.</param>
  935. /// <param name="objTag">Additional object tag.</param>
  936. /// <param name="strOriginal">Original string.</param>
  937. /// <param name="keyword">Keyword to replace.</param>
  938. /// <param name="formulaType">Formula used to calculate the value.</param>
  939. /// <param name="valueType">AxisName of value.</param>
  940. /// <param name="defaultFormat">Default format string.</param>
  941. /// <returns>Result string.</returns>
  942. internal string ReplaceOneKeyword(
  943. Chart chart,
  944. object obj,
  945. object objTag,
  946. ChartElementType elementType,
  947. string strOriginal,
  948. string keyword,
  949. SeriesValuesFormulaType formulaType,
  950. ChartValueType valueType,
  951. string defaultFormat)
  952. {
  953. string result = strOriginal;
  954. int keyIndex = -1;
  955. while((keyIndex = result.IndexOf(keyword, StringComparison.Ordinal)) != -1)
  956. {
  957. int keyEndIndex = keyIndex + keyword.Length;
  958. // Get optional Y value index
  959. int yValueIndex = 0;
  960. if(result.Length > keyEndIndex + 1 &&
  961. result[keyEndIndex] == 'Y' &&
  962. char.IsDigit(result[keyEndIndex + 1]))
  963. {
  964. yValueIndex = int.Parse(result.Substring(keyEndIndex + 1, 1), CultureInfo.InvariantCulture);
  965. keyEndIndex += 2;
  966. }
  967. // Get optional format
  968. string format = defaultFormat;
  969. if(result.Length > keyEndIndex && result[keyEndIndex] == '{')
  970. {
  971. int formatEnd = result.IndexOf('}', keyEndIndex);
  972. if(formatEnd == -1)
  973. {
  974. throw(new InvalidOperationException( SR.ExceptionDataSeriesKeywordFormatInvalid( result )));
  975. }
  976. format = result.Substring(keyEndIndex, formatEnd - keyEndIndex).Trim('{', '}');
  977. keyEndIndex = formatEnd + 1;
  978. }
  979. // Remove keyword string (with optional format)
  980. result = result.Remove(keyIndex, keyEndIndex - keyIndex);
  981. // Calculate value
  982. double totalValue = this.GetTotalYValue(yValueIndex);
  983. double keywordValue = 0.0;
  984. switch(formulaType)
  985. {
  986. case(SeriesValuesFormulaType.Average):
  987. {
  988. if(this.Points.Count > 0)
  989. {
  990. keywordValue = totalValue / this.Points.Count;
  991. }
  992. break;
  993. }
  994. case(SeriesValuesFormulaType.First):
  995. {
  996. if(this.Points.Count > 0)
  997. {
  998. keywordValue = this.Points[0].YValues[yValueIndex];
  999. }
  1000. break;
  1001. }
  1002. case(SeriesValuesFormulaType.Last):
  1003. {
  1004. if(this.Points.Count > 0)
  1005. {
  1006. keywordValue = this.Points[this.Points.Count - 1].YValues[yValueIndex];
  1007. }
  1008. break;
  1009. }
  1010. case(SeriesValuesFormulaType.Maximum):
  1011. {
  1012. if (this.Points.Count > 0)
  1013. {
  1014. keywordValue = double.MinValue;
  1015. foreach (DataPoint point in this.Points)
  1016. {
  1017. keywordValue = Math.Max(keywordValue, point.YValues[yValueIndex]);
  1018. }
  1019. }
  1020. break;
  1021. }
  1022. case(SeriesValuesFormulaType.Minimum):
  1023. {
  1024. if (this.Points.Count > 0)
  1025. {
  1026. keywordValue = double.MaxValue;
  1027. foreach (DataPoint point in this.Points)
  1028. {
  1029. keywordValue = Math.Min(keywordValue, point.YValues[yValueIndex]);
  1030. }
  1031. }
  1032. break;
  1033. }
  1034. case(SeriesValuesFormulaType.Total):
  1035. {
  1036. keywordValue = totalValue;
  1037. break;
  1038. }
  1039. }
  1040. // Insert value
  1041. result = result.Insert(keyIndex,
  1042. ValueConverter.FormatValue(chart, obj, objTag, keywordValue, format, valueType, elementType));
  1043. }
  1044. return result;
  1045. }
  1046. /// <summary>
  1047. /// Helper function which replaces one keyword.
  1048. /// </summary>
  1049. /// <param name="chart">Chart object reference.</param>
  1050. /// <param name="elementType">Chart element type.</param>
  1051. /// <param name="obj">Object being formatted.</param>
  1052. /// <param name="objTag">Additional object tag.</param>
  1053. /// <param name="strOriginal">Original string.</param>
  1054. /// <param name="keyword">Keyword to replace.</param>
  1055. /// <param name="value">Value to replace with.</param>
  1056. /// <param name="valueType">AxisName of value.</param>
  1057. /// <param name="defaultFormat">Default format string.</param>
  1058. /// <returns>Result string.</returns>
  1059. internal string ReplaceOneKeyword(Chart chart, object obj, object objTag, ChartElementType elementType, string strOriginal, string keyword, double value, ChartValueType valueType, string defaultFormat)
  1060. {
  1061. string result = strOriginal;
  1062. int keyIndex = -1;
  1063. while((keyIndex = result.IndexOf(keyword, StringComparison.Ordinal)) != -1)
  1064. {
  1065. // Get optional format
  1066. int keyEndIndex = keyIndex + keyword.Length;
  1067. string format = defaultFormat;
  1068. if(result.Length > keyEndIndex && result[keyEndIndex] == '{')
  1069. {
  1070. int formatEnd = result.IndexOf('}', keyEndIndex);
  1071. if(formatEnd == -1)
  1072. {
  1073. throw(new InvalidOperationException( SR.ExceptionDataSeriesKeywordFormatInvalid(result)));
  1074. }
  1075. format = result.Substring(keyEndIndex, formatEnd - keyEndIndex).Trim('{', '}');
  1076. keyEndIndex = formatEnd + 1;
  1077. }
  1078. // Remove keyword string (with optional format)
  1079. result = result.Remove(keyIndex, keyEndIndex - keyIndex);
  1080. // Insert value
  1081. result = result.Insert(keyIndex,
  1082. ValueConverter.FormatValue(chart, obj, objTag, value, format, valueType, elementType));
  1083. }
  1084. return result;
  1085. }
  1086. #endregion
  1087. #region Points sorting methods
  1088. /// <summary>
  1089. /// Sorts the points in the series.
  1090. /// </summary>
  1091. /// <param name="pointSortOrder">Sorting order.</param>
  1092. /// <param name="sortBy">Value used for sorting (X, Y, Y2, ...).</param>
  1093. public void Sort(PointSortOrder pointSortOrder, string sortBy)
  1094. {
  1095. // Check arguments
  1096. if (sortBy==null)
  1097. throw new ArgumentNullException("sortBy");
  1098. // Sort items using data points comparer class
  1099. DataPointComparer comparer = new DataPointComparer(this, pointSortOrder, sortBy);
  1100. this.Points.ItemList.Sort(comparer);
  1101. // Invalidate chart area only
  1102. this.Invalidate(true, false);
  1103. }
  1104. /// <summary>
  1105. /// Sorts the points in the series.
  1106. /// </summary>
  1107. /// <param name="pointSortOrder">Sorting order.</param>
  1108. public void Sort(PointSortOrder pointSortOrder)
  1109. {
  1110. Sort(pointSortOrder, "Y");
  1111. }
  1112. /// <summary>
  1113. /// Sorts the points in the series using IComparer interface.
  1114. /// </summary>
  1115. /// <param name="comparer">IComparer interface.</param>
  1116. public void Sort(IComparer<DataPoint> comparer)
  1117. {
  1118. // Check arguments
  1119. if (comparer == null)
  1120. throw new ArgumentNullException("comparer");
  1121. // Sort points
  1122. this.Points.ItemList.Sort(comparer);
  1123. // Invalidate chart area only
  1124. this.Invalidate(true, false);
  1125. }
  1126. #endregion
  1127. #region Series preparation/cleanup for drawing
  1128. /// <summary>
  1129. /// Moves the position markers.
  1130. /// </summary>
  1131. /// <param name="fromSeries">From series.</param>
  1132. /// <param name="toSeries">To series.</param>
  1133. internal static void MovePositionMarkers(Series fromSeries, Series toSeries)
  1134. {
  1135. foreach (DataPoint dp in fromSeries.Points)
  1136. {
  1137. if (dp.IsCustomPropertySet("OriginalPointIndex"))
  1138. {
  1139. int index = -1;
  1140. if (Int32.TryParse(dp["OriginalPointIndex"], NumberStyles.Integer, CultureInfo.InvariantCulture, out index))
  1141. {
  1142. if (index > -1 && index < toSeries.Points.Count)
  1143. {
  1144. toSeries.Points[index].positionRel = dp.positionRel;
  1145. }
  1146. }
  1147. }
  1148. }
  1149. }
  1150. /// <summary>
  1151. /// Called after the series was drawn.
  1152. /// </summary>
  1153. /// <param name="controlSite">Site interface of the control.</param>
  1154. /// <returns>True if series was removed from collection.</returns>
  1155. [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification = "This parameter is used when compiling for the WinForms version of Chart")]
  1156. internal bool UnPrepareData(ISite controlSite)
  1157. {
  1158. bool result = false;
  1159. // Process Renko chart type data calculations
  1160. if(RenkoChart.UnPrepareData(this))
  1161. {
  1162. result = true;
  1163. }
  1164. // Process ThreeLineBreak chart type data calculations
  1165. if(ThreeLineBreakChart.UnPrepareData(this))
  1166. {
  1167. result = true;
  1168. }
  1169. // Process Kagi chart type data calculations
  1170. if(KagiChart.UnPrepareData(this))
  1171. {
  1172. result = true;
  1173. }
  1174. // Process PointAndFigure chart type data calculations
  1175. if(PointAndFigureChart.UnPrepareData(this))
  1176. {
  1177. result = true;
  1178. }
  1179. // Undo all changes done for the collected slice support
  1180. if(PieChart.UnPrepareData(this))
  1181. {
  1182. result = true;
  1183. }
  1184. // Reset original value type which was temp. set to String
  1185. if(_isXValueIndexed)
  1186. {
  1187. _xValueType = indexedXValueType;
  1188. }
  1189. // Reset auro values only at design time
  1190. bool reset = false;
  1191. if(controlSite != null && controlSite.DesignMode)
  1192. {
  1193. reset = true;
  1194. }
  1195. ResetAutoValues(reset);
  1196. return result;
  1197. }
  1198. /// <summary>
  1199. /// Reset auto calculated series values.
  1200. /// </summary>
  1201. internal void ResetAutoValues()
  1202. {
  1203. ResetAutoValues(true);
  1204. }
  1205. /// <summary>
  1206. /// Reset auto calculated series values.
  1207. /// </summary>
  1208. /// <param name="reset">Indicates that value types should be reset.</param>
  1209. internal void ResetAutoValues(bool reset)
  1210. {
  1211. // If temporary data attribute is set - remove all data points
  1212. if(this.IsCustomPropertySet("TempDesignData"))
  1213. {
  1214. this.DeleteCustomProperty("TempDesignData");
  1215. // save the fake DataPoints for selector service
  1216. bool savePoints = true;
  1217. if (this.Chart != null && !this.Chart.IsDesignMode())
  1218. {
  1219. savePoints = false;
  1220. }
  1221. if ( savePoints )
  1222. {
  1223. fakeDataPoints.Clear();
  1224. foreach (DataPoint p in this.Points)
  1225. {
  1226. fakeDataPoints.Add(p);
  1227. }
  1228. }
  1229. this.Points.Clear();
  1230. }
  1231. // Reset series color
  1232. if(this.tempColorIsSet)
  1233. {
  1234. this.tempColorIsSet = false;
  1235. this.Color = Color.Empty;
  1236. }
  1237. // Reset series marker
  1238. if(this.tempMarkerStyleIsSet)
  1239. {
  1240. this.tempMarkerStyleIsSet = false;
  1241. this.MarkerStyle = MarkerStyle.None;
  1242. }
  1243. // Reset points color
  1244. foreach(DataPoint dataPoint in _points)
  1245. {
  1246. if(dataPoint.tempColorIsSet)
  1247. {
  1248. dataPoint.Color = Color.Empty;
  1249. }
  1250. }
  1251. // Reset value type to Auto (if not Serializing data)
  1252. if(reset)
  1253. {
  1254. if(this.Chart == null || this.Chart.serializing == false)
  1255. {
  1256. if(autoXValueType)
  1257. {
  1258. _xValueType = ChartValueType.Auto;
  1259. autoXValueType = false;
  1260. }
  1261. if(autoYValueType)
  1262. {
  1263. _yValueType = ChartValueType.Auto;
  1264. autoYValueType = false;
  1265. }
  1266. }
  1267. }
  1268. }
  1269. /// <summary>
  1270. /// Called just before the data from the series to be used to perform these operations:
  1271. /// - apply palette colors to the data points
  1272. /// - fill empty data points
  1273. /// - provide fake data in design mode
  1274. /// - retrieving data from the DataSource
  1275. /// </summary>
  1276. /// <param name="applyPaletteColors">If true each data point will be assigned a color from the palette (if it's set)</param>
  1277. internal void PrepareData(bool applyPaletteColors)
  1278. {
  1279. if(!this.IsVisible())
  1280. {
  1281. return;
  1282. }
  1283. // Series chart area name can be empty or a valid area name
  1284. Chart.ChartAreas.VerifyNameReference(this.ChartArea);
  1285. // Check if sereis data points have required number of Y values
  1286. if(this.Points.Count > 0 && this.Points[0].YValues.Length < this.YValuesPerPoint)
  1287. {
  1288. // Resize data points Y value(s) arrays
  1289. foreach(DataPoint dp in this.Points)
  1290. {
  1291. dp.ResizeYValueArray(this.YValuesPerPoint);
  1292. }
  1293. }
  1294. // Get series data source
  1295. bool fillTempData = false;
  1296. if(this.Points.Count == 0)
  1297. {
  1298. // If there is no points defined in design-time
  1299. if(Chart.IsDesignMode())
  1300. {
  1301. fillTempData = true;
  1302. }
  1303. else if(this.IsCustomPropertySet("UseDummyData"))
  1304. {
  1305. if(String.Compare(this["UseDummyData"], "True", StringComparison.OrdinalIgnoreCase) == 0)
  1306. {
  1307. fillTempData = true;
  1308. }
  1309. }
  1310. }
  1311. // Create dummy data only if there was no points
  1312. if(fillTempData)
  1313. {
  1314. if(this.IsXValueDateTime() || _xValueType == ChartValueType.String)
  1315. {
  1316. this.Points.DataBindXY(GetDummyData(_xValueType), GetDummyData(_yValueType));
  1317. }
  1318. else
  1319. {
  1320. double[] xValues = new double[] { 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 };
  1321. if(this.ChartType == SeriesChartType.Polar)
  1322. {
  1323. xValues = new double[] { 0.0, 45.0, 115.0, 145.0, 180.0, 220.0 };
  1324. }
  1325. this.Points.DataBindXY(xValues, GetDummyData(_yValueType));
  1326. }
  1327. // If point has more than one Y value - copy the data from first value
  1328. if(this.YValuesPerPoint > 1)
  1329. {
  1330. foreach(DataPoint point in this.Points)
  1331. {
  1332. for(int valueIndex = 1; valueIndex < this.YValuesPerPoint; valueIndex++)
  1333. {
  1334. point.YValues[valueIndex] = point.YValues[0];
  1335. }
  1336. if(this.YValuesPerPoint >= 2)
  1337. {
  1338. point.YValues[1] = point.YValues[0] / 2 - 1;
  1339. }
  1340. if(this.YValuesPerPoint >= 4)
  1341. {
  1342. point.YValues[2] = point.YValues[1] + (point.YValues[0] - point.YValues[1]) / 3;
  1343. point.YValues[3] = point.YValues[2] + (point.YValues[0] - point.YValues[1]) / 3;
  1344. }
  1345. if(this.YValuesPerPoint >= 6)
  1346. {
  1347. point.YValues[4] = point.YValues[2] + (point.YValues[3] - point.YValues[2]) / 2;
  1348. point.YValues[5] = point.YValues[2] + (point.YValues[3] - point.YValues[2]) / 3;
  1349. }
  1350. }
  1351. }
  1352. // Set data series attribute that data is temporary
  1353. this["TempDesignData"] = "true";
  1354. }
  1355. // If value type was not Auto detected - set it to double
  1356. if(_xValueType == ChartValueType.Auto)
  1357. {
  1358. _xValueType = ChartValueType.Double;
  1359. autoXValueType = true;
  1360. }
  1361. if(_yValueType == ChartValueType.Auto)
  1362. {
  1363. _yValueType = ChartValueType.Double;
  1364. autoYValueType = true;
  1365. }
  1366. // Use data point index as X value
  1367. indexedXValueType = _xValueType;
  1368. // Reset total Y value
  1369. _totalYvalue = double.NaN;
  1370. // Supress zero and negative values with logarithmic axis exceptions
  1371. if(this.Chart != null && this.Chart.chartPicture.SuppressExceptions)
  1372. {
  1373. // Get series axis
  1374. Axis axisY = this.Chart.ChartAreas[this.ChartArea].GetAxis(AxisName.Y, this.YAxisType, this.YSubAxisName);
  1375. foreach(DataPoint point in this.Points)
  1376. {
  1377. for(int yValueIndex = 0; yValueIndex < point.YValues.Length; yValueIndex++)
  1378. {
  1379. if(axisY.IsLogarithmic)
  1380. {
  1381. // Look for Y values less or equal to Zero
  1382. if(point.YValues[yValueIndex] <= 0.0)
  1383. {
  1384. point.YValues[yValueIndex] = 1.0;
  1385. point.IsEmpty = true;
  1386. }
  1387. }
  1388. // Check All Y values for NaN
  1389. if(double.IsNaN(point.YValues[yValueIndex]))
  1390. {
  1391. point.YValues[yValueIndex] = 0.0;
  1392. point.IsEmpty = true;
  1393. }
  1394. }
  1395. }
  1396. }
  1397. // Process Error Bar chart type data linking and calculations
  1398. ErrorBarChart.GetDataFromLinkedSeries(this);
  1399. ErrorBarChart.CalculateErrorAmount(this);
  1400. // Process Box chart type data calculations
  1401. BoxPlotChart.CalculateBoxPlotFromLinkedSeries(this);
  1402. // Process Renko chart type data calculations
  1403. RenkoChart.PrepareData(this);
  1404. // Process ThreeLineBreak chart type data calculations
  1405. ThreeLineBreakChart.PrepareData(this);
  1406. // Process Kagi chart type data calculations
  1407. KagiChart.PrepareData(this);
  1408. // Process PointAndFigure chart type data calculations
  1409. PointAndFigureChart.PrepareData(this);
  1410. // Check if Collected slice should be displayed in Pie/Doughnut charts
  1411. PieChart.PrepareData(this);
  1412. // Apply palette colors to the data points
  1413. if (applyPaletteColors)
  1414. {
  1415. this.ApplyPaletteColors();
  1416. }
  1417. }
  1418. #endregion
  1419. #region Series Properties
  1420. /// <summary>
  1421. /// Data series name.
  1422. /// </summary>
  1423. [
  1424. SRCategory("CategoryAttributeData"),
  1425. Bindable(true),
  1426. SRDescription("DescriptionAttributeSeries_Name"),
  1427. ]
  1428. public override string Name
  1429. {
  1430. get
  1431. {
  1432. return base.Name;
  1433. }
  1434. set
  1435. {
  1436. base.Name = value;
  1437. CallOnModifing();
  1438. }
  1439. }
  1440. /// <summary>
  1441. /// Member of the chart data source used to data bind to the X value of the series.
  1442. /// </summary>
  1443. [
  1444. SRCategory("CategoryAttributeDataSource"),
  1445. Bindable(true),
  1446. SRDescription("DescriptionAttributeSeries_ValueMemberX"),
  1447. DefaultValue(""),
  1448. TypeConverter(typeof(SeriesDataSourceMemberConverter))
  1449. ]
  1450. public string XValueMember
  1451. {
  1452. get
  1453. {
  1454. return _dataSourceXMember;
  1455. }
  1456. set
  1457. {
  1458. if(value == "(none)")
  1459. {
  1460. _dataSourceXMember = String.Empty;
  1461. }
  1462. else
  1463. {
  1464. _dataSourceXMember = value;
  1465. }
  1466. // Reset data bound flag
  1467. if(this.Common!=null && this.Common.ChartPicture!=null)
  1468. {
  1469. this.Common.ChartPicture.boundToDataSource = false;
  1470. }
  1471. CallOnModifing();
  1472. }
  1473. }
  1474. /// <summary>
  1475. /// Members of the chart data source used to data bind to the Y values of the series.
  1476. /// </summary>
  1477. [
  1478. SRCategory("CategoryAttributeDataSource"),
  1479. Bindable(true),
  1480. SRDescription("DescriptionAttributeSeries_ValueMembersY"),
  1481. DefaultValue(""),
  1482. TypeConverter(typeof(SeriesDataSourceMemberConverter)),
  1483. #if DESIGNER
  1484. Editor(typeof(SeriesDataSourceMemberValueAxisUITypeEditor), typeof(UITypeEditor))
  1485. #endif
  1486. ]
  1487. public string YValueMembers
  1488. {
  1489. get
  1490. {
  1491. return _dataSourceYMembers;
  1492. }
  1493. set
  1494. {
  1495. if(value == "(none)")
  1496. {
  1497. _dataSourceYMembers = String.Empty;
  1498. }
  1499. else
  1500. {
  1501. _dataSourceYMembers = value;
  1502. }
  1503. // Reset data bound flag
  1504. if(this.Common != null && this.Common.ChartPicture!=null)
  1505. {
  1506. this.Common.ChartPicture.boundToDataSource = false;
  1507. }
  1508. CallOnModifing();
  1509. }
  1510. }
  1511. /// <summary>
  1512. /// Name of the Chart legend used by the series.
  1513. /// </summary>
  1514. [
  1515. SRCategory("CategoryAttributeLegend"),
  1516. Bindable(true),
  1517. SRDescription("DescriptionAttributeSeries_Legend"),
  1518. DefaultValue(""),
  1519. TypeConverter(typeof(SeriesLegendNameConverter))
  1520. ]
  1521. public string Legend
  1522. {
  1523. get
  1524. {
  1525. return _legend;
  1526. }
  1527. set
  1528. {
  1529. if (value != _legend)
  1530. {
  1531. if (Chart != null && Chart.Legends != null)
  1532. {
  1533. Chart.Legends.VerifyNameReference(value);
  1534. }
  1535. _legend = value;
  1536. this.Invalidate(false, true);
  1537. CallOnModifing();
  1538. }
  1539. }
  1540. }
  1541. /// <summary>
  1542. /// The value type of the X axis.
  1543. /// </summary>
  1544. [
  1545. SRCategory("CategoryAttributeData"),
  1546. Bindable(true),
  1547. SRDescription("DescriptionAttributeSeries_XValueType"),
  1548. DefaultValue(ChartValueType.Auto)
  1549. ]
  1550. public ChartValueType XValueType
  1551. {
  1552. get
  1553. {
  1554. return _xValueType;
  1555. }
  1556. set
  1557. {
  1558. _xValueType = value;
  1559. this.autoXValueType = false;
  1560. this.Invalidate(true, false);
  1561. CallOnModifing();
  1562. }
  1563. }
  1564. /// <summary>
  1565. /// Indicates whether a data point index (1,2,...) will be used for the X value.
  1566. /// </summary>
  1567. [
  1568. SRCategory("CategoryAttributeData"),
  1569. Bindable(true),
  1570. SRDescription("DescriptionAttributeSeries_XValueIndexed"),
  1571. DefaultValue(false),
  1572. ]
  1573. public bool IsXValueIndexed
  1574. {
  1575. get
  1576. {
  1577. return _isXValueIndexed;
  1578. }
  1579. set
  1580. {
  1581. _isXValueIndexed = value;
  1582. this.Invalidate(true, false);
  1583. CallOnModifing();
  1584. }
  1585. }
  1586. /// <summary>
  1587. /// The value type of the Y axis.
  1588. /// </summary>
  1589. [
  1590. SRCategory("CategoryAttributeData"),
  1591. Bindable(true),
  1592. SRDescription("DescriptionAttributeSeries_YValueType"),
  1593. DefaultValue(ChartValueType.Auto),
  1594. TypeConverter(typeof(SeriesYValueTypeConverter))
  1595. ]
  1596. public ChartValueType YValueType
  1597. {
  1598. get
  1599. {
  1600. return _yValueType;
  1601. }
  1602. set
  1603. {
  1604. _yValueType = value;
  1605. this.autoYValueType = false;
  1606. this.Invalidate(true, false);
  1607. CallOnModifing();
  1608. }
  1609. }
  1610. /// <summary>
  1611. /// Number of Y values stored for each Data Point.
  1612. /// </summary>
  1613. [
  1614. SRCategory("CategoryAttributeData"),
  1615. Bindable(true),
  1616. SRDescription("DescriptionAttributeSeries_YValuesPerPoint"),
  1617. DefaultValue(1)
  1618. ]
  1619. public int YValuesPerPoint
  1620. {
  1621. get
  1622. {
  1623. // If number of Y value(s) is not set - get one from the chart type
  1624. if(this._checkPointsNumber && this.ChartTypeName.Length > 0 && this.Common != null)
  1625. {
  1626. _checkPointsNumber = false;
  1627. ChartTypeRegistry chartTypeRegistry = this.Common.ChartTypeRegistry;
  1628. IChartType chartType = chartTypeRegistry.GetChartType(this.ChartTypeName);
  1629. if(chartType.YValuesPerPoint > _yValuesPerPoint)
  1630. {
  1631. _yValuesPerPoint = chartType.YValuesPerPoint;
  1632. // Resize Y value(s) array of data points
  1633. if(_points.Count > 0)
  1634. {
  1635. // Resize data points Y value(s) arrays
  1636. foreach(DataPoint dp in _points)
  1637. {
  1638. dp.ResizeYValueArray(_yValuesPerPoint);
  1639. }
  1640. }
  1641. }
  1642. }
  1643. return _yValuesPerPoint;
  1644. }
  1645. set
  1646. {
  1647. // Check if argument is in range
  1648. if(value < 1 || value > 32)
  1649. {
  1650. throw (new ArgumentOutOfRangeException("value", SR.ExceptionDataSeriesYValueNumberInvalid));
  1651. }
  1652. _checkPointsNumber = true;
  1653. // Resize Y value(s) array of data points
  1654. if(_points.Count > 0)
  1655. {
  1656. // Resize data points Y value(s) arrays
  1657. foreach(DataPoint dp in _points)
  1658. {
  1659. dp.ResizeYValueArray(value);
  1660. }
  1661. }
  1662. _yValuesPerPoint = value;
  1663. this.Invalidate(true, false);
  1664. CallOnModifing();
  1665. }
  1666. }
  1667. /// <summary>
  1668. /// Collection of data points in the series.
  1669. /// </summary>
  1670. [
  1671. SRCategory("CategoryAttributeData"),
  1672. Bindable(true),
  1673. SRDescription("DescriptionAttributeSeries_Points"),
  1674. DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
  1675. #if DESIGNER
  1676. Editor(typeof(DataPointCollectionEditor), typeof(UITypeEditor))
  1677. #endif
  1678. ]
  1679. public DataPointCollection Points
  1680. {
  1681. get
  1682. {
  1683. return _points;
  1684. }
  1685. }
  1686. /// <summary>
  1687. /// Default properties of an empty data point.
  1688. /// </summary>
  1689. [
  1690. SRCategory("CategoryAttributeEmptyPoints"),
  1691. Bindable(true),
  1692. SRDescription("DescriptionAttributeSeries_EmptyPointStyle"),
  1693. DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
  1694. ]
  1695. public DataPointCustomProperties EmptyPointStyle
  1696. {
  1697. get
  1698. {
  1699. return _emptyPointCustomProperties;
  1700. }
  1701. set
  1702. {
  1703. if (value.series == null && _emptyPointCustomProperties.series != null)
  1704. {
  1705. value.series = _emptyPointCustomProperties.series;
  1706. }
  1707. _emptyPointCustomProperties = value;
  1708. _emptyPointCustomProperties.pointCustomProperties = false;
  1709. _emptyPointCustomProperties.SetDefault(false);
  1710. _emptyPointCustomProperties.pointCustomProperties = true;
  1711. _emptyPointCustomProperties.Parent = this;
  1712. this.Invalidate(true, false);
  1713. CallOnModifing();
  1714. }
  1715. }
  1716. /// <summary>
  1717. /// Color palette to use.
  1718. /// </summary>
  1719. [
  1720. SRCategory("CategoryAttributeAppearance"),
  1721. Bindable(true),
  1722. SRDescription("DescriptionAttributePalette"),
  1723. DefaultValue(ChartColorPalette.None),
  1724. #if DESIGNER
  1725. Editor(typeof(ColorPaletteEditor), typeof(UITypeEditor))
  1726. #endif
  1727. ]
  1728. public ChartColorPalette Palette
  1729. {
  1730. get
  1731. {
  1732. return _colorPalette;
  1733. }
  1734. set
  1735. {
  1736. _colorPalette = value;
  1737. this.Invalidate(true, true);
  1738. CallOnModifing();
  1739. }
  1740. }
  1741. /// <summary>
  1742. /// Specify how often to display data point markers.
  1743. /// </summary>
  1744. [
  1745. SRCategory("CategoryAttributeMarker"),
  1746. Bindable(true),
  1747. SRDescription("DescriptionAttributeSeries_MarkerStep"),
  1748. DefaultValue(1)
  1749. ]
  1750. public int MarkerStep
  1751. {
  1752. get
  1753. {
  1754. return _markersStep;
  1755. }
  1756. set
  1757. {
  1758. if(value <= 0)
  1759. {
  1760. throw(new ArgumentException( SR.ExceptionMarkerStepNegativeValue, "value"));
  1761. }
  1762. _markersStep = value;
  1763. this.Invalidate(true, false);
  1764. CallOnModifing();
  1765. }
  1766. }
  1767. /// <summary>
  1768. /// Shadow offset of series.
  1769. /// </summary>
  1770. [
  1771. SRCategory("CategoryAttributeAppearance"),
  1772. Bindable(true),
  1773. SRDescription("DescriptionAttributeShadowOffset"),
  1774. DefaultValue(0)
  1775. ]
  1776. public int ShadowOffset
  1777. {
  1778. get
  1779. {
  1780. return _shadowOffset;
  1781. }
  1782. set
  1783. {
  1784. _shadowOffset = value;
  1785. this.Invalidate(true, true);
  1786. CallOnModifing();
  1787. }
  1788. }
  1789. /// <summary>
  1790. /// Shadow color of series.
  1791. /// </summary>
  1792. [
  1793. SRCategory("CategoryAttributeAppearance"),
  1794. Bindable(true),
  1795. DefaultValue(typeof(Color), "128,0,0,0"),
  1796. SRDescription("DescriptionAttributeShadowColor"),
  1797. ]
  1798. public Color ShadowColor
  1799. {
  1800. get
  1801. {
  1802. return _shadowColor;
  1803. }
  1804. set
  1805. {
  1806. _shadowColor = value;
  1807. this.Invalidate(true, true);
  1808. CallOnModifing();
  1809. }
  1810. }
  1811. #if SUBAXES
  1812. /// <summary>
  1813. /// Name of the Y sub-axis this series is attached to.
  1814. /// </summary>
  1815. [
  1816. SRCategory("CategoryAttributeAxes"),
  1817. Bindable(true),
  1818. SRDescription("DescriptionAttributeSeries_YSubAxisName"),
  1819. DefaultValue("")
  1820. ]
  1821. public string YSubAxisName
  1822. {
  1823. get
  1824. {
  1825. return this._ySubAxisName;
  1826. }
  1827. set
  1828. {
  1829. this._ySubAxisName = value;
  1830. this.Invalidate(true, false);
  1831. }
  1832. }
  1833. /// <summary>
  1834. /// Name of the X sub-axis this series is attached to.
  1835. /// </summary>
  1836. [
  1837. SRCategory("CategoryAttributeAxes"),
  1838. Bindable(true),
  1839. SRDescription("DescriptionAttributeSeries_XSubAxisName"),
  1840. DefaultValue("")
  1841. ]
  1842. public string XSubAxisName
  1843. {
  1844. get
  1845. {
  1846. return this._xSubAxisName;
  1847. }
  1848. set
  1849. {
  1850. this._xSubAxisName = value;
  1851. this.Invalidate(true, false);
  1852. }
  1853. }
  1854. #else // SUBAXES
  1855. /// <summary>
  1856. /// Name of the Y sub-axis this series is attached to.
  1857. /// </summary>
  1858. [
  1859. SRCategory("CategoryAttributeAxes"),
  1860. Bindable(true),
  1861. SRDescription("DescriptionAttributeSeries_YSubAxisName"),
  1862. DefaultValue(""),
  1863. System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "value")
  1864. ]
  1865. internal string YSubAxisName
  1866. {
  1867. get
  1868. {
  1869. return string.Empty;
  1870. }
  1871. set
  1872. {
  1873. }
  1874. }
  1875. /// <summary>
  1876. /// Name of the X sub-axis this series is attached to.
  1877. /// </summary>
  1878. [
  1879. SRCategory("CategoryAttributeAxes"),
  1880. Bindable(true),
  1881. SRDescription("DescriptionAttributeSeries_XSubAxisName"),
  1882. DefaultValue(""),
  1883. System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "value")
  1884. ]
  1885. internal string XSubAxisName
  1886. {
  1887. get
  1888. {
  1889. return string.Empty;
  1890. }
  1891. set
  1892. {
  1893. }
  1894. }
  1895. #endif // SUBAXES
  1896. /// <summary>
  1897. /// Axis type of horizontal axes.
  1898. /// </summary>
  1899. [
  1900. SRCategory("CategoryAttributeAxes"),
  1901. Bindable(true),
  1902. SRDescription("DescriptionAttributeSeries_XAxisType"),
  1903. DefaultValue(AxisType.Primary)
  1904. ]
  1905. public AxisType XAxisType
  1906. {
  1907. get
  1908. {
  1909. return _xAxisType;
  1910. }
  1911. set
  1912. {
  1913. _xAxisType = value;
  1914. this.Invalidate(true, false);
  1915. CallOnModifing();
  1916. }
  1917. }
  1918. /// <summary>
  1919. /// Axis type of vertical axes.
  1920. /// </summary>
  1921. [
  1922. SRCategory("CategoryAttributeAxes"),
  1923. Bindable(true),
  1924. SRDescription("DescriptionAttributeSeries_YAxisType"),
  1925. DefaultValue(AxisType.Primary)
  1926. ]
  1927. public AxisType YAxisType
  1928. {
  1929. get
  1930. {
  1931. return _yAxisType;
  1932. }
  1933. set
  1934. {
  1935. _yAxisType = value;
  1936. this.Invalidate(true, false);
  1937. CallOnModifing();
  1938. }
  1939. }
  1940. /// <summary>
  1941. /// Gets or sets a flag which indicates whether the series is enabled.
  1942. /// </summary>
  1943. [
  1944. SRCategory("CategoryAttributeAppearance"),
  1945. Bindable(true),
  1946. DefaultValue(true),
  1947. SRDescription("DescriptionAttributeSeries_Enabled"),
  1948. NotifyParentPropertyAttribute(true),
  1949. ParenthesizePropertyNameAttribute(true),
  1950. ]
  1951. public bool Enabled
  1952. {
  1953. get
  1954. {
  1955. return _enabled;
  1956. }
  1957. set
  1958. {
  1959. _enabled = value;
  1960. this.Invalidate(true, true);
  1961. CallOnModifing();
  1962. }
  1963. }
  1964. /// <summary>
  1965. /// Chart type used to draw the series.
  1966. /// </summary>
  1967. [
  1968. SRCategory("CategoryAttributeChart"),
  1969. Bindable(true),
  1970. SRDescription("DescriptionAttributeSeries_Type"),
  1971. DefaultValue(SeriesChartType.Column),
  1972. RefreshProperties(RefreshProperties.All),
  1973. #if DESIGNER
  1974. Editor(typeof(ChartTypeEditor), typeof(UITypeEditor))
  1975. #endif
  1976. ]
  1977. public SeriesChartType ChartType
  1978. {
  1979. get
  1980. {
  1981. SeriesChartType type = SeriesChartType.Column;
  1982. if(String.Compare(this.ChartTypeName, ChartTypeNames.OneHundredPercentStackedArea, StringComparison.OrdinalIgnoreCase) == 0)
  1983. {
  1984. type = SeriesChartType.StackedArea100;
  1985. }
  1986. else if (String.Compare(this.ChartTypeName, ChartTypeNames.OneHundredPercentStackedBar, StringComparison.OrdinalIgnoreCase) == 0)
  1987. {
  1988. type = SeriesChartType.StackedBar100;
  1989. }
  1990. else if (String.Compare(this.ChartTypeName, ChartTypeNames.OneHundredPercentStackedColumn, StringComparison.OrdinalIgnoreCase) == 0)
  1991. {
  1992. type = SeriesChartType.StackedColumn100;
  1993. }
  1994. else
  1995. {
  1996. try
  1997. {
  1998. type = (SeriesChartType)Enum.Parse(typeof(SeriesChartType), this.ChartTypeName, true);
  1999. }
  2000. catch (ArgumentException)
  2001. {
  2002. }
  2003. }
  2004. return type;
  2005. }
  2006. set
  2007. {
  2008. this.ChartTypeName = Series.GetChartTypeName(value);
  2009. CallOnModifing();
  2010. }
  2011. }
  2012. /// <summary>
  2013. /// Chart type used to draw the series.
  2014. /// </summary>
  2015. [
  2016. Browsable(false),
  2017. EditorBrowsableAttribute(EditorBrowsableState.Never),
  2018. SRCategory("CategoryAttributeChart"),
  2019. Bindable(true),
  2020. SRDescription("DescriptionAttributeSeries_Type"),
  2021. DefaultValue(ChartTypeNames.Column),
  2022. TypeConverter(typeof(ChartTypeConverter)),
  2023. #if DESIGNER
  2024. Editor(typeof(ChartTypeEditor), typeof(UITypeEditor)),
  2025. #endif
  2026. RefreshProperties(RefreshProperties.All),
  2027. SerializationVisibilityAttribute(SerializationVisibility.Hidden),
  2028. DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)
  2029. ]
  2030. public string ChartTypeName
  2031. {
  2032. get
  2033. {
  2034. return _chartType;
  2035. }
  2036. set
  2037. {
  2038. if(_chartType != value && value.Length > 0)
  2039. {
  2040. if(Common != null)
  2041. {
  2042. ChartTypeRegistry chartTypeRegistry = Common.ChartTypeRegistry;
  2043. if(chartTypeRegistry != null)
  2044. {
  2045. IChartType type = chartTypeRegistry.GetChartType(value);
  2046. if(_yValuesPerPoint < type.YValuesPerPoint)
  2047. {
  2048. // Set minimum Y values number for the chart type
  2049. _yValuesPerPoint = type.YValuesPerPoint;
  2050. // Resize Y value(s) array of data points
  2051. if(_points.Count > 0)
  2052. {
  2053. // Resize data points Y value(s) arrays
  2054. foreach(DataPoint dp in _points)
  2055. {
  2056. dp.ResizeYValueArray(_yValuesPerPoint);
  2057. }
  2058. }
  2059. }
  2060. // Refresh Minimum and Maximum from data
  2061. // after recalc and set data
  2062. if(Chart != null && Chart.chartPicture != null)
  2063. {
  2064. Chart.chartPicture.ResetMinMaxFromData();
  2065. }
  2066. }
  2067. }
  2068. }
  2069. _chartType = value;
  2070. this.Invalidate(false, true);
  2071. }
  2072. }
  2073. /// <summary>
  2074. /// Chart area in which this series is drawn.
  2075. /// </summary>
  2076. [
  2077. SRCategory("CategoryAttributeChart"),
  2078. Bindable(true),
  2079. SRDescription("DescriptionAttributeSeries_ChartArea"),
  2080. DefaultValue(""),
  2081. TypeConverter(typeof(SeriesAreaNameConverter))
  2082. ]
  2083. public string ChartArea
  2084. {
  2085. get
  2086. {
  2087. return _chartArea;
  2088. }
  2089. set
  2090. {
  2091. if (value != _chartArea)
  2092. {
  2093. if (Chart != null && Chart.ChartAreas != null)
  2094. {
  2095. Chart.ChartAreas.VerifyNameReference(value);
  2096. }
  2097. _chartArea = value;
  2098. this.Invalidate(false, true);
  2099. CallOnModifing();
  2100. }
  2101. }
  2102. }
  2103. /*
  2104. /// <summary>
  2105. /// If set to true, each data point of the series will use a random color from the palette.
  2106. /// </summary>
  2107. [
  2108. SRCategory("CategoryAttributeChart"),
  2109. Bindable(true),
  2110. SRDescription("DescriptionAttributeDataSeriesGroupID"),
  2111. PersistenceModeAttribute(PersistenceMode.Attribute),
  2112. DefaultValue("")
  2113. ]
  2114. public string GroupID
  2115. {
  2116. get
  2117. {
  2118. return groupID;
  2119. }
  2120. set
  2121. {
  2122. groupID = value;
  2123. }
  2124. }
  2125. */
  2126. /// <summary>
  2127. /// Text of X axis label.
  2128. /// </summary>
  2129. [
  2130. Browsable(false),
  2131. SRCategory("CategoryAttributeMisc"),
  2132. Bindable(true),
  2133. DefaultValue(""),
  2134. SRDescription("DescriptionAttributeAxisLabel"),
  2135. ]
  2136. override public string AxisLabel
  2137. {
  2138. get
  2139. {
  2140. return base.AxisLabel;
  2141. }
  2142. set
  2143. {
  2144. base.AxisLabel = value;
  2145. this.Invalidate(true, false);
  2146. }
  2147. }
  2148. /// <summary>
  2149. /// Style of the SmartLabel.
  2150. /// </summary>
  2151. [
  2152. Browsable(true),
  2153. SRCategory("CategoryAttributeLabel"),
  2154. Bindable(true),
  2155. SRDescription("DescriptionAttributeSeries_SmartLabels"),
  2156. DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
  2157. ]
  2158. public SmartLabelStyle SmartLabelStyle
  2159. {
  2160. get
  2161. {
  2162. return _smartLabelStyle;
  2163. }
  2164. set
  2165. {
  2166. value.chartElement = this;
  2167. _smartLabelStyle = value;
  2168. this.Invalidate(false, false);
  2169. CallOnModifing();
  2170. }
  2171. }
  2172. /// <summary>
  2173. /// Series font cache is reused by points.
  2174. /// </summary>
  2175. /// <value>The font cache.</value>
  2176. internal FontCache FontCache
  2177. {
  2178. get { return _fontCache; }
  2179. }
  2180. #endregion
  2181. #region Invalidating method
  2182. /// <summary>
  2183. /// Invalidate chart or just a chart area and/or legend when collection is changed
  2184. /// </summary>
  2185. /// <param name="invalidateAreaOnly">Invalidate chart area only.</param>
  2186. /// <param name="invalidateLegend">Invalidate legend area only.</param>
  2187. [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification = "This parameter is used when compiling for the WinForms version of Chart")]
  2188. internal void Invalidate(bool invalidateAreaOnly, bool invalidateLegend)
  2189. {
  2190. if(Chart != null)
  2191. {
  2192. if(!invalidateAreaOnly)
  2193. {
  2194. this.Invalidate();
  2195. }
  2196. else
  2197. {
  2198. // Invalidate one chart area (area with this name may not exist)
  2199. try
  2200. {
  2201. Chart.ChartAreas[this.ChartArea].Invalidate();
  2202. }
  2203. catch(ArgumentException)
  2204. {
  2205. // occurs if the chart area is not found in the collection
  2206. }
  2207. // Invalidate legend
  2208. if(invalidateLegend && Chart.Legends.IndexOf(this.Legend) >= 0)
  2209. {
  2210. Chart.Legends[this.Legend].Invalidate(true);
  2211. }
  2212. }
  2213. }
  2214. }
  2215. #endregion
  2216. #region Series Enumeration
  2217. /// <summary>
  2218. /// Series values formula type used in the keywords
  2219. /// </summary>
  2220. internal enum SeriesValuesFormulaType
  2221. {
  2222. Total,
  2223. Average,
  2224. Maximum,
  2225. Minimum,
  2226. First,
  2227. Last
  2228. }
  2229. #endregion // Series Enumeration
  2230. #region IDisposable Members
  2231. /// <summary>
  2232. /// Releases unmanaged and - optionally - managed resources
  2233. /// </summary>
  2234. /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
  2235. protected override void Dispose(bool disposing)
  2236. {
  2237. if (disposing)
  2238. {
  2239. if (_fontCache != null)
  2240. {
  2241. _fontCache.Dispose();
  2242. _fontCache = null;
  2243. }
  2244. if (this._emptyPointCustomProperties != null)
  2245. {
  2246. this._emptyPointCustomProperties.Dispose();
  2247. this._emptyPointCustomProperties = null;
  2248. }
  2249. if (this._points != null)
  2250. {
  2251. this._points.Dispose();
  2252. this._points = null;
  2253. }
  2254. if (this.fakeDataPoints != null)
  2255. {
  2256. this.fakeDataPoints.Dispose();
  2257. this.fakeDataPoints = null;
  2258. }
  2259. }
  2260. base.Dispose(disposing);
  2261. }
  2262. #endregion
  2263. }
  2264. }