Selection.cs 106 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197
  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: This file contains methods used for Win Form selection
  6. //
  7. using System;
  8. using System.Windows.Forms;
  9. using System.Collections;
  10. using System.Collections.Generic;
  11. using System.Collections.ObjectModel;
  12. using System.ComponentModel.Design;
  13. using System.Diagnostics.CodeAnalysis;
  14. using System.Drawing;
  15. using System.Drawing.Drawing2D;
  16. using System.Globalization;
  17. using System.Text;
  18. namespace FastReport.DataVisualization.Charting
  19. {
  20. using Point = System.Drawing.Point;
  21. #region Enumerations
  22. // Plase keep the folowing enumaration in chart layering order - ex. ChartArea is under DataPoint
  23. /// <summary>
  24. /// An enumeration of types of Chart Element.
  25. /// </summary>
  26. public enum ChartElementType
  27. {
  28. /// <summary>
  29. /// No chart element.
  30. /// </summary>
  31. Nothing,
  32. /// <summary>
  33. /// The title of a chart.
  34. /// </summary>
  35. Title,
  36. /// <summary>
  37. /// Plotting area (chart area excluding axes, labels, etc.).
  38. /// Also excludes the regions that data points may occupy.
  39. /// </summary>
  40. PlottingArea,
  41. /// <summary>
  42. /// An Axis object.
  43. /// </summary>
  44. Axis,
  45. /// <summary>
  46. /// Any major or minor tick mark.
  47. /// </summary>
  48. TickMarks,
  49. /// <summary>
  50. /// Any major or minor grid line (both vertical or horizontal).
  51. /// </summary>
  52. Gridlines,
  53. /// <summary>
  54. /// A StripLine object.
  55. /// </summary>
  56. StripLines,
  57. /// <summary>
  58. /// Axis label Image.
  59. /// </summary>
  60. AxisLabelImage,
  61. /// <summary>
  62. /// Axis labels
  63. /// </summary>
  64. AxisLabels,
  65. /// <summary>
  66. /// Axis title
  67. /// </summary>
  68. AxisTitle,
  69. /// <summary>
  70. /// A scrollbar tracking thumb.
  71. /// </summary>
  72. ScrollBarThumbTracker,
  73. /// <summary>
  74. /// A scrollbar small decrement button. A "down arrow"
  75. /// button for a vertical scrollbar, or a "left arrow"
  76. /// button for a horizontal scroll bar.
  77. /// </summary>
  78. ScrollBarSmallDecrement,
  79. /// <summary>
  80. /// A scrollbar small increment button. An "up arrow"
  81. /// button for a vertical scrollbar, or a "right arrow"
  82. /// button for a horizontal scroll bar.
  83. /// </summary>
  84. ScrollBarSmallIncrement,
  85. /// <summary>
  86. /// The background of a scrollbar that will result in
  87. /// a large decrement in the scale view size when clicked.
  88. /// This is the background below the thumb for
  89. /// a vertical scrollbar, and to the left of
  90. /// the thumb for a horizontal scrollbar.
  91. /// </summary>
  92. ScrollBarLargeDecrement,
  93. /// <summary>
  94. /// The background of a scrollbar that will result in
  95. /// a large increment in the scale view size when clicked.
  96. /// This is the background above the thumb for
  97. /// a vertical scrollbar, and to the right of
  98. /// the thumb for a horizontal scrollbar.
  99. /// </summary>
  100. ScrollBarLargeIncrement,
  101. /// <summary>
  102. /// The zoom reset button of a scrollbar.
  103. /// </summary>
  104. ScrollBarZoomReset,
  105. /// <summary>
  106. /// A DataPoint object.
  107. /// </summary>
  108. DataPoint,
  109. /// <summary>
  110. /// Series data point label.
  111. /// </summary>
  112. DataPointLabel,
  113. /// <summary>
  114. /// The area inside a Legend object. Does not include
  115. /// the space occupied by legend items.
  116. /// </summary>
  117. LegendArea,
  118. /// <summary>
  119. /// Legend title.
  120. /// </summary>
  121. LegendTitle,
  122. /// <summary>
  123. /// Legend header.
  124. /// </summary>
  125. LegendHeader,
  126. /// <summary>
  127. /// A LegendItem object.
  128. /// </summary>
  129. LegendItem,
  130. /// <summary>
  131. /// Chart annotation object.
  132. /// </summary>
  133. Annotation,
  134. }
  135. /// <summary>
  136. /// Enumeration (Flag) used for processing chart types.
  137. /// </summary>
  138. [Flags]
  139. internal enum ProcessMode
  140. {
  141. /// <summary>
  142. /// Paint mode
  143. /// </summary>
  144. Paint = 1,
  145. /// <summary>
  146. /// Selection mode. Collection of hot regions has to be created.
  147. /// </summary>
  148. HotRegions = 2,
  149. /// <summary>
  150. /// Used for image maps
  151. /// </summary>
  152. ImageMaps = 4
  153. }
  154. #endregion
  155. /// <summary>
  156. /// This class presents item in
  157. /// the collection of hot regions.
  158. /// </summary>
  159. internal class HotRegion : IDisposable
  160. {
  161. #region Fields
  162. // Private data members, which store properties values
  163. private GraphicsPath _path = null;
  164. private bool _relativeCoordinates = true;
  165. private RectangleF _boundingRectangle = RectangleF.Empty;
  166. private object _selectedObject = null;
  167. private int _pointIndex = -1;
  168. private string _seriesName = "";
  169. private ChartElementType _type = ChartElementType.Nothing;
  170. private object _selectedSubObject = null;
  171. #endregion // Fields
  172. #region Properties
  173. /// <summary>
  174. /// Region is Graphics path
  175. /// </summary>
  176. internal GraphicsPath Path
  177. {
  178. get
  179. {
  180. return _path;
  181. }
  182. set
  183. {
  184. _path = value;
  185. }
  186. }
  187. /// <summary>
  188. /// Relative coordinates are used
  189. /// to define region
  190. /// </summary>
  191. internal bool RelativeCoordinates
  192. {
  193. get
  194. {
  195. return _relativeCoordinates;
  196. }
  197. set
  198. {
  199. _relativeCoordinates = value;
  200. }
  201. }
  202. /// <summary>
  203. /// Bounding Rectangle of an shape
  204. /// </summary>
  205. internal RectangleF BoundingRectangle
  206. {
  207. get
  208. {
  209. return _boundingRectangle;
  210. }
  211. set
  212. {
  213. _boundingRectangle = value;
  214. }
  215. }
  216. /// <summary>
  217. /// Object which is presented with this region
  218. /// </summary>
  219. internal object SelectedObject
  220. {
  221. get
  222. {
  223. return _selectedObject;
  224. }
  225. set
  226. {
  227. _selectedObject = value;
  228. }
  229. }
  230. /// <summary>
  231. /// Sub-Object which is presented with this region
  232. /// </summary>
  233. internal object SelectedSubObject
  234. {
  235. get
  236. {
  237. return _selectedSubObject;
  238. }
  239. set
  240. {
  241. _selectedSubObject = value;
  242. }
  243. }
  244. /// <summary>
  245. /// Index of the data point which is presented with this region
  246. /// </summary>
  247. internal int PointIndex
  248. {
  249. get
  250. {
  251. return _pointIndex;
  252. }
  253. set
  254. {
  255. _pointIndex = value;
  256. }
  257. }
  258. /// <summary>
  259. /// Name of the series which is presented with the region
  260. /// </summary>
  261. internal string SeriesName
  262. {
  263. get
  264. {
  265. return _seriesName;
  266. }
  267. set
  268. {
  269. _seriesName = value;
  270. }
  271. }
  272. /// <summary>
  273. /// Chart Element AxisName
  274. /// </summary>
  275. internal ChartElementType Type
  276. {
  277. get
  278. {
  279. return _type;
  280. }
  281. set
  282. {
  283. _type = value;
  284. }
  285. }
  286. #endregion // Properties
  287. #region IDisposable members
  288. /// <summary>
  289. /// Releases unmanaged and - optionally - managed resources
  290. /// </summary>
  291. /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
  292. protected virtual void Dispose(bool disposing)
  293. {
  294. if (disposing)
  295. {
  296. if (_path != null)
  297. {
  298. _path.Dispose();
  299. _path = null;
  300. }
  301. }
  302. }
  303. /// <summary>
  304. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  305. /// </summary>
  306. public void Dispose()
  307. {
  308. Dispose(true);
  309. GC.SuppressFinalize(this);
  310. }
  311. #endregion
  312. #region Methods
  313. /// <summary>
  314. /// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
  315. /// </summary>
  316. /// <returns>
  317. /// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
  318. /// </returns>
  319. public override string ToString()
  320. {
  321. string objectType = this.SelectedObject != null ? this.SelectedObject.ToString() : "null";
  322. if (this.SelectedObject == null && !String.IsNullOrEmpty(this.SeriesName))
  323. {
  324. objectType = this.SeriesName;
  325. }
  326. return String.Format(CultureInfo.CurrentCulture, "{0} of {1}", this.Type, objectType);
  327. }
  328. #endregion //Methods
  329. }
  330. /// <summary>
  331. /// This class is used to fill and
  332. /// manage collection with Hot Regions
  333. /// </summary>
  334. internal class HotRegionsList : IDisposable
  335. {
  336. #region Fields
  337. /// <summary>
  338. /// Process chart mode Flag
  339. /// </summary>
  340. private ProcessMode _processChartMode = ProcessMode.Paint;
  341. /// <summary>
  342. /// Collection with Hor Region Elements
  343. /// </summary>
  344. private System.Collections.ArrayList _regionList = new ArrayList();
  345. /// <summary>
  346. /// Reference to the common elements object
  347. /// </summary>
  348. private CommonElements _common = null;
  349. /// <summary>
  350. /// True if hit test function is called
  351. /// </summary>
  352. internal bool hitTestCalled = false;
  353. #endregion // Fields
  354. #region Properties
  355. /// <summary>
  356. /// Flag used for processing chart types. It could
  357. /// be Paint, HotRegion or both mode.
  358. /// </summary>
  359. internal ProcessMode ProcessChartMode
  360. {
  361. get
  362. {
  363. return _processChartMode;
  364. }
  365. set
  366. {
  367. _processChartMode = value;
  368. if(this._common != null)
  369. {
  370. this._common.processModePaint =
  371. (_processChartMode & ProcessMode.Paint ) == ProcessMode.Paint;
  372. this._common.processModeRegions =
  373. ( _processChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions ||
  374. ( _processChartMode & ProcessMode.ImageMaps ) == ProcessMode.ImageMaps;
  375. }
  376. }
  377. }
  378. /// <summary>
  379. /// Collection with Hor Region Elements
  380. /// </summary>
  381. internal ArrayList List
  382. {
  383. get
  384. {
  385. return _regionList;
  386. }
  387. }
  388. #endregion // Properties
  389. #region Methods
  390. /// <summary>
  391. /// Constructor
  392. /// </summary>
  393. /// <param name="common">Reference to the CommonElements</param>
  394. internal HotRegionsList( CommonElements common )
  395. {
  396. this._common = common;
  397. }
  398. /// <summary>
  399. /// Add hot region to the collection.
  400. /// </summary>
  401. /// <param name="rectSize">Rectangle which presents an Hot Region</param>
  402. /// <param name="point">Data Point</param>
  403. /// <param name="seriesName">Data Series</param>
  404. /// <param name="pointIndex">Index of an Data Point in the series</param>
  405. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
  406. public void AddHotRegion(
  407. RectangleF rectSize,
  408. DataPoint point,
  409. string seriesName,
  410. int pointIndex
  411. )
  412. {
  413. if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
  414. {
  415. HotRegion region = new HotRegion();
  416. region.BoundingRectangle = rectSize;
  417. region.SeriesName = seriesName;
  418. region.PointIndex = pointIndex;
  419. region.Type = ChartElementType.DataPoint;
  420. region.RelativeCoordinates = true;
  421. // Use index of the original data point
  422. if(point != null && point.IsCustomPropertySet("OriginalPointIndex"))
  423. {
  424. region.PointIndex = int.Parse(point["OriginalPointIndex"], CultureInfo.InvariantCulture);
  425. }
  426. _regionList.Add( region );
  427. }
  428. }
  429. /// <summary>
  430. /// Adds the hot region.
  431. /// </summary>
  432. /// <param name="path">Bounding GraphicsPath.</param>
  433. /// <param name="relativePath">if set to <c>true</c> the is relative path.</param>
  434. /// <param name="graph">Chart Graphics Object</param>
  435. /// <param name="point">Selected data point</param>
  436. /// <param name="seriesName">Name of the series.</param>
  437. /// <param name="pointIndex">Index of the point.</param>
  438. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "graph")]
  439. internal void AddHotRegion(
  440. GraphicsPath path,
  441. bool relativePath,
  442. ChartGraphics graph,
  443. DataPoint point,
  444. string seriesName,
  445. int pointIndex
  446. )
  447. {
  448. if( path == null )
  449. {
  450. return;
  451. }
  452. if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
  453. {
  454. HotRegion region = new HotRegion();
  455. region.SeriesName = seriesName;
  456. region.PointIndex = pointIndex;
  457. region.Type = ChartElementType.DataPoint;
  458. region.Path = (GraphicsPath)path.Clone();
  459. region.BoundingRectangle = path.GetBounds();
  460. region.RelativeCoordinates = relativePath;
  461. // Use index of the original data point
  462. if(point != null && point.IsCustomPropertySet("OriginalPointIndex"))
  463. {
  464. region.PointIndex = int.Parse(point["OriginalPointIndex"], CultureInfo.InvariantCulture);
  465. }
  466. _regionList.Add( region );
  467. }
  468. }
  469. /// <summary>
  470. /// Adds the hot region.
  471. /// </summary>
  472. /// <param name="insertIndex">Position where to insert element. Used for image maps only</param>
  473. /// <param name="path">Bounding GraphicsPath.</param>
  474. /// <param name="relativePath">if set to <c>true</c> the is relative path.</param>
  475. /// <param name="graph">Chart Graphics Object</param>
  476. /// <param name="point">Selected data point</param>
  477. /// <param name="seriesName">Name of the series.</param>
  478. /// <param name="pointIndex">Index of the point.</param>
  479. [
  480. System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "graph"),
  481. System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "insertIndex")
  482. ]
  483. internal void AddHotRegion(
  484. int insertIndex,
  485. GraphicsPath path,
  486. bool relativePath,
  487. ChartGraphics graph,
  488. DataPoint point,
  489. string seriesName,
  490. int pointIndex
  491. )
  492. {
  493. if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
  494. {
  495. HotRegion region = new HotRegion();
  496. region.SeriesName = seriesName;
  497. region.PointIndex = pointIndex;
  498. region.Type = ChartElementType.DataPoint;
  499. region.Path = (GraphicsPath)path.Clone();
  500. region.BoundingRectangle = path.GetBounds();
  501. region.RelativeCoordinates = relativePath;
  502. // Use index of the original data point
  503. if(point != null && point.IsCustomPropertySet("OriginalPointIndex"))
  504. {
  505. region.PointIndex = int.Parse(point["OriginalPointIndex"], CultureInfo.InvariantCulture);
  506. }
  507. _regionList.Add( region );
  508. }
  509. }
  510. /// <summary>
  511. /// Add hot region to the collection.
  512. /// </summary>
  513. /// <param name="path">Graphics path which presents hot region</param>
  514. /// <param name="relativePath">Graphics path uses relative or absolute coordinates</param>
  515. /// <param name="coord">Coordinates which defines polygon (Graphics Path). Used for image maps</param>
  516. /// <param name="point">Selected data point</param>
  517. /// <param name="seriesName">Data Series</param>
  518. /// <param name="pointIndex">Index of an Data Point in the series</param>
  519. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "coord")]
  520. internal void AddHotRegion( GraphicsPath path, bool relativePath, float [] coord, DataPoint point, string seriesName, int pointIndex )
  521. {
  522. if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
  523. {
  524. HotRegion region = new HotRegion();
  525. region.SeriesName = seriesName;
  526. region.PointIndex = pointIndex;
  527. region.Type = ChartElementType.DataPoint;
  528. region.Path = (GraphicsPath)path.Clone();
  529. region.BoundingRectangle = path.GetBounds();
  530. region.RelativeCoordinates = relativePath;
  531. // Use index of the original data point
  532. if(point != null && point.IsCustomPropertySet("OriginalPointIndex"))
  533. {
  534. region.PointIndex = int.Parse(point["OriginalPointIndex"], CultureInfo.InvariantCulture);
  535. }
  536. _regionList.Add( region );
  537. }
  538. }
  539. /// <summary>
  540. /// Add Hot region to the collection.
  541. /// </summary>
  542. /// <param name="insertIndex">Position where to insert element. Used for image maps only</param>
  543. /// <param name="graph">Chart Graphics Object</param>
  544. /// <param name="x">x coordinate.</param>
  545. /// <param name="y">y coordinate.</param>
  546. /// <param name="radius">The radius.</param>
  547. /// <param name="point">Selected data point</param>
  548. /// <param name="seriesName">Data Series</param>
  549. /// <param name="pointIndex">Index of an Data Point in the series</param>
  550. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "insertIndex")]
  551. internal void AddHotRegion( int insertIndex, ChartGraphics graph, float x, float y, float radius, DataPoint point, string seriesName, int pointIndex )
  552. {
  553. if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
  554. {
  555. HotRegion region = new HotRegion();
  556. PointF circleCenter = graph.GetAbsolutePoint( new PointF( x, y ) );
  557. SizeF circleRadius = graph.GetAbsoluteSize( new SizeF( radius, radius ) );
  558. GraphicsPath path = new GraphicsPath();
  559. path.AddEllipse(
  560. circleCenter.X - circleRadius.Width,
  561. circleCenter.Y - circleRadius.Width,
  562. 2 * circleRadius.Width,
  563. 2 * circleRadius.Width
  564. );
  565. region.BoundingRectangle = path.GetBounds();
  566. region.SeriesName = seriesName;
  567. region.Type = ChartElementType.DataPoint;
  568. region.PointIndex = pointIndex;
  569. region.Path = path;
  570. region.RelativeCoordinates = false;
  571. // Use index of the original data point
  572. if(point != null && point.IsCustomPropertySet("OriginalPointIndex"))
  573. {
  574. region.PointIndex = int.Parse(point["OriginalPointIndex"], CultureInfo.InvariantCulture);
  575. }
  576. _regionList.Add( region );
  577. }
  578. }
  579. /// <summary>
  580. /// Add Hot region to the collection.
  581. /// </summary>
  582. /// <param name="rectArea">Hot Region rectangle</param>
  583. /// <param name="toolTip">Tool Tip Text</param>
  584. /// <param name="hRef">HRef string</param>
  585. /// <param name="mapAreaAttributes">Map area Attribute string</param>
  586. /// <param name="postBackValue">The post back value associated with this item</param>
  587. /// <param name="selectedObject">Object which present hot region</param>
  588. /// <param name="type">AxisName of the object which present hot region</param>
  589. /// <param name="series">Selected series</param>
  590. [
  591. System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "hRef"),
  592. System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "mapAreaAttributes"),
  593. System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "postBackValue"),
  594. System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "toolTip")
  595. ]
  596. internal void AddHotRegion( RectangleF rectArea, string toolTip, string hRef, string mapAreaAttributes, string postBackValue, object selectedObject, ChartElementType type, string series )
  597. {
  598. if ( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
  599. {
  600. HotRegion region = new HotRegion();
  601. region.BoundingRectangle = rectArea;
  602. region.RelativeCoordinates = true;
  603. region.Type = type;
  604. region.SelectedObject = selectedObject;
  605. if(!String.IsNullOrEmpty(series))
  606. {
  607. region.SeriesName = series;
  608. }
  609. _regionList.Add( region );
  610. }
  611. }
  612. /// <summary>
  613. /// Add Hot region to the collection.
  614. /// </summary>
  615. /// <param name="rectArea">Hot Region rectangle</param>
  616. /// <param name="toolTip">Tool Tip Text</param>
  617. /// <param name="hRef">HRef string</param>
  618. /// <param name="mapAreaAttributes">Map area Attribute string</param>
  619. /// <param name="postBackValue">The post back value associated with this item</param>
  620. /// <param name="selectedObject">Object which present hot region</param>
  621. /// <param name="selectedSubObject">Sub-Object which present hot region</param>
  622. /// <param name="type">AxisName of the object which present hot region</param>
  623. /// <param name="series">Selected series</param>
  624. [
  625. System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "hRef"),
  626. System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "mapAreaAttributes"),
  627. System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "postBackValue"),
  628. System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "toolTip")
  629. ]
  630. internal void AddHotRegion(
  631. RectangleF rectArea,
  632. string toolTip,
  633. string hRef,
  634. string mapAreaAttributes,
  635. string postBackValue,
  636. object selectedObject,
  637. object selectedSubObject,
  638. ChartElementType type,
  639. string series )
  640. {
  641. if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
  642. {
  643. HotRegion region = new HotRegion();
  644. region.BoundingRectangle = rectArea;
  645. region.RelativeCoordinates = true;
  646. region.Type = type;
  647. region.SelectedObject = selectedObject;
  648. region.SelectedSubObject = selectedSubObject;
  649. if(!String.IsNullOrEmpty(series))
  650. {
  651. region.SeriesName = series;
  652. }
  653. _regionList.Add( region );
  654. }
  655. }
  656. /// <summary>
  657. /// Add Hot region to the collection.
  658. /// </summary>
  659. /// <param name="graph">Chart Graphics Object</param>
  660. /// <param name="path">Graphics path</param>
  661. /// <param name="relativePath">Used relative coordinates for graphics path.</param>
  662. /// <param name="toolTip">Tool Tip Text</param>
  663. /// <param name="hRef">HRef string</param>
  664. /// <param name="mapAreaAttributes">Map area Attribute string</param>
  665. /// <param name="postBackValue">The post back value associated with this item</param>
  666. /// <param name="selectedObject">Object which present hot region</param>
  667. /// <param name="type">AxisName of the object which present hot region</param>
  668. [
  669. System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "graph"),
  670. System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "hRef"),
  671. System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "mapAreaAttributes"),
  672. System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "postBackValue"),
  673. System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "toolTip")
  674. ]
  675. internal void AddHotRegion( ChartGraphics graph, GraphicsPath path, bool relativePath, string toolTip, string hRef, string mapAreaAttributes, string postBackValue, object selectedObject, ChartElementType type )
  676. {
  677. if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
  678. {
  679. HotRegion region = new HotRegion();
  680. region.Type = type;
  681. region.Path = (GraphicsPath)path.Clone();
  682. region.SelectedObject = selectedObject;
  683. region.BoundingRectangle = path.GetBounds();
  684. region.RelativeCoordinates = relativePath;
  685. _regionList.Add( region );
  686. }
  687. }
  688. /// <summary>
  689. /// Add Hot region to the collection.
  690. /// </summary>
  691. /// <param name="rectArea">Hot Region rectangle</param>
  692. /// <param name="selectedObject">Object which present hot region</param>
  693. /// <param name="type">AxisName of the object which present hot region</param>
  694. /// <param name="relativeCoordinates">Coordinates for rectangle are relative</param>
  695. internal void AddHotRegion( RectangleF rectArea, object selectedObject, ChartElementType type, bool relativeCoordinates )
  696. {
  697. this.AddHotRegion( rectArea, selectedObject, type, relativeCoordinates, false );
  698. }
  699. /// <summary>
  700. /// Add Hot region to the collection.
  701. /// </summary>
  702. /// <param name="rectArea">Hot Region rectangle</param>
  703. /// <param name="selectedObject">Object which present hot region</param>
  704. /// <param name="type">AxisName of the object which present hot region</param>
  705. /// <param name="relativeCoordinates">Coordinates for rectangle are relative</param>
  706. /// <param name="insertAtBeginning">Insert the hot region at the beginning of the collection</param>
  707. internal void AddHotRegion( RectangleF rectArea, object selectedObject, ChartElementType type, bool relativeCoordinates, bool insertAtBeginning )
  708. {
  709. if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
  710. {
  711. HotRegion region = new HotRegion();
  712. region.BoundingRectangle = rectArea;
  713. region.RelativeCoordinates = relativeCoordinates;
  714. region.Type = type;
  715. region.SelectedObject = selectedObject;
  716. if( insertAtBeginning )
  717. {
  718. _regionList.Insert( _regionList.Count - 1, region );
  719. }
  720. else
  721. {
  722. _regionList.Add( region );
  723. }
  724. }
  725. }
  726. /// <summary>
  727. /// Add Hot region to the collection.
  728. /// </summary>
  729. /// <param name="path">Graphics path</param>
  730. /// <param name="relativePath">Used relative coordinates for graphics path.</param>
  731. /// <param name="type">Type of the object which present hot region</param>
  732. /// <param name="selectedObject">Object which present hot region</param>
  733. internal void AddHotRegion(
  734. GraphicsPath path,
  735. bool relativePath,
  736. ChartElementType type,
  737. object selectedObject
  738. )
  739. {
  740. if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
  741. {
  742. HotRegion region = new HotRegion();
  743. region.SelectedObject = selectedObject;
  744. region.Type = type;
  745. region.Path = (GraphicsPath)path.Clone();
  746. region.BoundingRectangle = path.GetBounds();
  747. region.RelativeCoordinates = relativePath;
  748. _regionList.Add( region );
  749. }
  750. }
  751. /// <summary>
  752. /// This method search for position in Map Areas which is the first
  753. /// position after Custom areas.
  754. /// </summary>
  755. /// <returns>Insert Index</returns>
  756. internal int FindInsertIndex()
  757. {
  758. int insertIndex = 0;
  759. return insertIndex;
  760. }
  761. /// <summary>
  762. /// Clears this instance.
  763. /// </summary>
  764. public void Clear()
  765. {
  766. foreach (HotRegion hotRegion in this._regionList)
  767. hotRegion.Dispose();
  768. this._regionList.Clear();
  769. }
  770. #endregion // Methods
  771. #region IDisposable members
  772. /// <summary>
  773. /// Releases unmanaged and - optionally - managed resources
  774. /// </summary>
  775. /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
  776. protected virtual void Dispose(bool disposing)
  777. {
  778. if (disposing)
  779. {
  780. if (this._regionList != null)
  781. {
  782. foreach (HotRegion hotRegion in this._regionList)
  783. hotRegion.Dispose();
  784. this._regionList.Clear();
  785. }
  786. }
  787. }
  788. /// <summary>
  789. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  790. /// </summary>
  791. public void Dispose()
  792. {
  793. Dispose(true);
  794. GC.SuppressFinalize(this);
  795. }
  796. #endregion
  797. }
  798. /// <summary>
  799. /// The HitTestResult class contains the result of the hit test function.
  800. /// </summary>
  801. public class HitTestResult
  802. {
  803. #region Fields
  804. // Private members
  805. private object _obj = null;
  806. private Series _series = null;
  807. private int _dataPoint = -1;
  808. private ChartArea _chartArea = null;
  809. private Axis _axis = null;
  810. private ChartElementType _type = ChartElementType.Nothing;
  811. private object _subObject = null;
  812. #endregion
  813. #region Properties
  814. /// <summary>
  815. /// Gets or sets the data series object.
  816. /// </summary>
  817. public Series Series
  818. {
  819. get
  820. {
  821. return _series;
  822. }
  823. set
  824. {
  825. _series = value;
  826. }
  827. }
  828. /// <summary>
  829. /// Gets or sets the data point index.
  830. /// </summary>
  831. public int PointIndex
  832. {
  833. get
  834. {
  835. return _dataPoint;
  836. }
  837. set
  838. {
  839. _dataPoint = value;
  840. }
  841. }
  842. /// <summary>
  843. /// Gets or sets the chart area object.
  844. /// </summary>
  845. public ChartArea ChartArea
  846. {
  847. get
  848. {
  849. return _chartArea;
  850. }
  851. set
  852. {
  853. _chartArea = value;
  854. }
  855. }
  856. /// <summary>
  857. /// Gets or sets the axis object.
  858. /// </summary>
  859. public Axis Axis
  860. {
  861. get
  862. {
  863. return _axis;
  864. }
  865. set
  866. {
  867. _axis = value;
  868. }
  869. }
  870. /// <summary>
  871. /// Gets or sets the chart element type.
  872. /// </summary>
  873. public ChartElementType ChartElementType
  874. {
  875. get
  876. {
  877. return _type;
  878. }
  879. set
  880. {
  881. _type = value;
  882. }
  883. }
  884. /// <summary>
  885. /// Gets or sets the selected object.
  886. /// </summary>
  887. public object Object
  888. {
  889. get
  890. {
  891. return _obj;
  892. }
  893. set
  894. {
  895. _obj = value;
  896. }
  897. }
  898. /// <summary>
  899. /// Gets or sets the selected sub object.
  900. /// </summary>
  901. public object SubObject
  902. {
  903. get
  904. {
  905. return _subObject;
  906. }
  907. set
  908. {
  909. _subObject = value;
  910. }
  911. }
  912. #endregion
  913. }
  914. /// <summary>
  915. /// This class represents an array of marker points and
  916. /// the outline path used for visual object selection in the chart.
  917. /// </summary>
  918. /// <remarks>
  919. /// <see cref="OutlinePath"/> may be null for complex objects or objects with two points or fewer.
  920. /// </remarks>
  921. public class ChartElementOutline : IDisposable
  922. {
  923. /// <summary>
  924. /// Initializes a new instance of the <see cref="ChartElementOutline"/> class.
  925. /// </summary>
  926. internal ChartElementOutline()
  927. {
  928. this.Markers = new ReadOnlyCollection<PointF>( new PointF[] {});
  929. }
  930. /// <summary>
  931. /// Gets the markers.
  932. /// </summary>
  933. /// <value>The markers.</value>
  934. public ReadOnlyCollection<PointF> Markers { get; internal set; }
  935. /// <summary>
  936. /// Gets or sets the outline path. The result could be null for complex objects and objects with two points or fewer.
  937. /// </summary>
  938. /// <value>The outline path.</value>
  939. public GraphicsPath OutlinePath { get; internal set; }
  940. #region IDisposable Members
  941. /// <summary>
  942. /// Releases unmanaged and - optionally - managed resources
  943. /// </summary>
  944. /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
  945. protected virtual void Dispose(bool disposing)
  946. {
  947. if (disposing)
  948. {
  949. if (this.OutlinePath != null)
  950. {
  951. this.OutlinePath.Dispose();
  952. this.OutlinePath = null;
  953. }
  954. this.Markers = null;
  955. }
  956. }
  957. /// <summary>
  958. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  959. /// </summary>
  960. [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
  961. public void Dispose()
  962. {
  963. Dispose(true);
  964. GC.SuppressFinalize(this);
  965. }
  966. #endregion
  967. }
  968. /// <summary>
  969. /// This class contains methods used for Windows Forms selection.
  970. /// </summary>
  971. internal class Selection : IServiceProvider
  972. , IDisposable
  973. {
  974. #region Fields
  975. /// <summary>
  976. /// The chart service container
  977. /// </summary>
  978. private IServiceContainer _service = null;
  979. /// <summary>
  980. /// Stores the tooltip of the control.
  981. /// </summary>
  982. private ToolTip _toolTip = new ToolTip();
  983. /// <summary>
  984. /// Used by the tooltip - stores the time when the tooltip is activated.
  985. /// </summary>
  986. private DateTime _toolTipActivationTime = DateTime.Now;
  987. /// <summary>
  988. /// Stores the last mouse move X and Y coordinates, so we can ignore false calls to
  989. /// OnMouseMove generated my the tooltip.
  990. /// </summary>
  991. private Point _lastMouseMove = new Point(int.MinValue, int.MinValue);
  992. // ToolTips enabled or disabled from series or legend
  993. private bool _toolTipsEnabled = false;
  994. // Tool tips enabled flag checked
  995. internal bool enabledChecked = false;
  996. #endregion
  997. #region Constructors
  998. /// <summary>
  999. /// Initializes a new instance of the <see cref="Selection"/> class.
  1000. /// </summary>
  1001. /// <param name="service">The service.</param>
  1002. internal Selection(IServiceContainer service)
  1003. {
  1004. this._service = service;
  1005. this._chartControl = this.ChartControl;
  1006. // Set up the tooltip
  1007. this._toolTip.Active = true;
  1008. this._toolTip.AutoPopDelay = 30000; // maximum delay possible
  1009. this._toolTip.InitialDelay = 500;
  1010. this._toolTip.ReshowDelay = 50;
  1011. this._toolTip.ShowAlways = true;
  1012. this._toolTip.Active = false;
  1013. }
  1014. /// <summary>
  1015. /// Releases unmanaged and - optionally - managed resources
  1016. /// </summary>
  1017. /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
  1018. private void Dispose(bool disposing)
  1019. {
  1020. if (disposing)
  1021. {
  1022. if (_toolTip != null)
  1023. {
  1024. _toolTip.Dispose();
  1025. _toolTip = null;
  1026. }
  1027. }
  1028. }
  1029. /// <summary>
  1030. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  1031. /// </summary>
  1032. public void Dispose()
  1033. {
  1034. Dispose(true);
  1035. GC.SuppressFinalize(this);
  1036. }
  1037. #endregion //Constructors
  1038. #region Properties
  1039. private Chart _chartControl = null;
  1040. /// <summary>
  1041. /// Returns the attached chart control
  1042. /// </summary>
  1043. internal Chart ChartControl
  1044. {
  1045. get
  1046. {
  1047. if (this._chartControl == null)
  1048. {
  1049. if (this.ChartPicture != null)
  1050. {
  1051. this._chartControl = this.ChartPicture.Chart;
  1052. }
  1053. }
  1054. return this._chartControl;
  1055. }
  1056. }
  1057. private ChartPicture _chartPicture = null;
  1058. /// <summary>
  1059. /// Returns the attached ChartPicture
  1060. /// </summary>
  1061. internal ChartPicture ChartPicture
  1062. {
  1063. get
  1064. {
  1065. if (this._chartPicture == null)
  1066. {
  1067. this._chartPicture = ((IServiceProvider)this).GetService(typeof(ChartImage)) as ChartPicture;
  1068. if (this._chartPicture == null)
  1069. {
  1070. this._chartPicture = ((IServiceProvider)this).GetService(typeof(ChartPicture)) as ChartPicture;
  1071. }
  1072. }
  1073. return this._chartPicture;
  1074. }
  1075. }
  1076. private Data.DataManager _dataManager = null;
  1077. /// <summary>
  1078. /// Gets the chart data manager ( for series access )
  1079. /// </summary>
  1080. internal Data.DataManager DataManager
  1081. {
  1082. get
  1083. {
  1084. if (this._dataManager == null)
  1085. {
  1086. this._dataManager = ((IServiceProvider)this).GetService(typeof(Data.DataManager)) as Data.DataManager;
  1087. }
  1088. return this._dataManager;
  1089. }
  1090. }
  1091. /// <summary>
  1092. /// Gets the chart ChartGraphics
  1093. /// </summary>
  1094. internal ChartGraphics Graph
  1095. {
  1096. get
  1097. {
  1098. if (this.ChartPicture != null)
  1099. {
  1100. return this.ChartPicture.Common.graph;
  1101. }
  1102. return null;
  1103. }
  1104. }
  1105. #endregion //Private Properties
  1106. #region Methods
  1107. #region Tooltips
  1108. /// <summary>
  1109. /// Checks if tooltips are enabled
  1110. /// </summary>
  1111. /// <returns>true if tooltips enabled</returns>
  1112. private bool IsToolTipsEnabled()
  1113. {
  1114. // Enabled checked. Don’t check every time series
  1115. // and data points for tooltips.
  1116. if( enabledChecked )
  1117. {
  1118. return _toolTipsEnabled;
  1119. }
  1120. enabledChecked = true;
  1121. // Annotations loop
  1122. foreach( Annotation annotation in _chartControl.Annotations )
  1123. {
  1124. // ToolTip empty
  1125. if( annotation.ToolTip.Length > 0 )
  1126. {
  1127. // ToolTips enabled
  1128. _toolTipsEnabled = true;
  1129. return true;
  1130. }
  1131. }
  1132. // Data series loop
  1133. foreach( Series series in _chartControl.Series )
  1134. {
  1135. // Check series tooltips
  1136. if( series.ToolTip.Length > 0 ||
  1137. series.LegendToolTip.Length > 0 ||
  1138. series.LabelToolTip.Length > 0)
  1139. {
  1140. // ToolTips enabled
  1141. _toolTipsEnabled = true;
  1142. return true;
  1143. }
  1144. // Check if custom properties (Pie collected slice) that create tooltips are used
  1145. if(series.IsCustomPropertySet(Utilities.CustomPropertyName.CollectedToolTip))
  1146. {
  1147. // ToolTips enabled
  1148. _toolTipsEnabled = true;
  1149. return true;
  1150. }
  1151. // Check point tooltips only for "non-Fast" chart types
  1152. if( !series.IsFastChartType() )
  1153. {
  1154. // Data point loop
  1155. foreach( DataPoint point in series.Points )
  1156. {
  1157. // ToolTip empty
  1158. if( point.ToolTip.Length > 0 ||
  1159. point.LegendToolTip.Length > 0 ||
  1160. point.LabelToolTip.Length > 0)
  1161. {
  1162. // ToolTips enabled
  1163. _toolTipsEnabled = true;
  1164. return true;
  1165. }
  1166. }
  1167. }
  1168. }
  1169. // Legend items loop
  1170. foreach( Legend legend in _chartControl.Legends )
  1171. {
  1172. // Check custom legend items
  1173. foreach( LegendItem legendItem in legend.CustomItems )
  1174. {
  1175. // ToolTip empty
  1176. if( legendItem.ToolTip.Length > 0 )
  1177. {
  1178. _toolTipsEnabled = true;
  1179. return true;
  1180. }
  1181. // Check all custom cells in the legend item
  1182. foreach(LegendCell legendCell in legendItem.Cells)
  1183. {
  1184. if(legendCell.ToolTip.Length > 0)
  1185. {
  1186. _toolTipsEnabled = true;
  1187. return true;
  1188. }
  1189. }
  1190. }
  1191. // Iterate through legend columns
  1192. foreach(LegendCellColumn legendColumn in legend.CellColumns)
  1193. {
  1194. if(legendColumn.ToolTip.Length > 0)
  1195. {
  1196. _toolTipsEnabled = true;
  1197. return true;
  1198. }
  1199. }
  1200. }
  1201. // Title items loop
  1202. foreach( Title title in _chartControl.Titles )
  1203. {
  1204. // ToolTip empty
  1205. if( title.ToolTip.Length > 0 )
  1206. {
  1207. _toolTipsEnabled = true;
  1208. return true;
  1209. }
  1210. }
  1211. // Chart areas loop
  1212. foreach( ChartArea area in _chartControl.ChartAreas )
  1213. {
  1214. // Check if chart area is visible
  1215. if(area.Visible)
  1216. {
  1217. // Axis loop
  1218. foreach(Axis axis in area.Axes)
  1219. {
  1220. // Check ToolTip
  1221. if( axis.ToolTip.Length > 0 )
  1222. {
  1223. _toolTipsEnabled = true;
  1224. return true;
  1225. }
  1226. // Strip lines loop
  1227. foreach(StripLine stripLine in axis.StripLines)
  1228. {
  1229. // Check ToolTip
  1230. if( stripLine.ToolTip.Length > 0 )
  1231. {
  1232. _toolTipsEnabled = true;
  1233. return true;
  1234. }
  1235. }
  1236. // Check custom labels
  1237. foreach(CustomLabel customLabel in axis.CustomLabels)
  1238. {
  1239. if( customLabel.ToolTip.Length > 0 )
  1240. {
  1241. _toolTipsEnabled = true;
  1242. return true;
  1243. }
  1244. }
  1245. }
  1246. }
  1247. }
  1248. // ToolTips disabled
  1249. _toolTipsEnabled = false;
  1250. return false;
  1251. }
  1252. [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily",
  1253. Justification = "Too large of a code change to justify making this change")]
  1254. internal string EvaluateToolTip(System.Windows.Forms.MouseEventArgs e)
  1255. {
  1256. object obj;
  1257. object subObj;
  1258. ChartElementType type;
  1259. int dataPointIndex;
  1260. string seriesName;
  1261. string toolTipText = " ";
  1262. HitTestResult hitTest = this.HitTest(e.X, e.Y, true);
  1263. type = hitTest.ChartElementType;
  1264. dataPointIndex = hitTest.PointIndex;
  1265. seriesName = hitTest.Series != null ? hitTest.Series.Name : String.Empty;
  1266. obj = hitTest.Object;
  1267. subObj = hitTest.SubObject;
  1268. // Get tooltips from data points
  1269. if (type == ChartElementType.DataPoint)
  1270. {
  1271. if (_chartControl.Series.IndexOf(seriesName) >= 0 &&
  1272. dataPointIndex >= 0 &&
  1273. dataPointIndex < _chartControl.Series[seriesName].Points.Count)
  1274. {
  1275. // Take tool tip from data point
  1276. toolTipText = _chartControl.Series[seriesName].Points[dataPointIndex].ReplaceKeywords(_chartControl.Series[seriesName].Points[dataPointIndex].ToolTip);
  1277. }
  1278. else
  1279. {
  1280. DataPoint dataPoint = obj as DataPoint;
  1281. if (dataPoint != null)
  1282. {
  1283. // Take tool tip from data point
  1284. toolTipText = dataPoint.ReplaceKeywords(dataPoint.ToolTip);
  1285. }
  1286. }
  1287. }
  1288. // Get tooltips from data points
  1289. if (type == ChartElementType.DataPointLabel)
  1290. {
  1291. if (_chartControl.Series.IndexOf(seriesName) >= 0 &&
  1292. dataPointIndex >= 0 &&
  1293. dataPointIndex < _chartControl.Series[seriesName].Points.Count)
  1294. {
  1295. // Take tool tip from data point
  1296. toolTipText = _chartControl.Series[seriesName].Points[dataPointIndex].ReplaceKeywords(_chartControl.Series[seriesName].Points[dataPointIndex].LabelToolTip);
  1297. }
  1298. }
  1299. // Get tooltips from custom label
  1300. if (type == ChartElementType.AxisLabels &&
  1301. obj is CustomLabel)
  1302. {
  1303. toolTipText = ((CustomLabel)obj).ToolTip;
  1304. }
  1305. // Get tooltips from data points
  1306. else if (type == ChartElementType.Annotation && obj != null && obj is Annotation)
  1307. {
  1308. // Take tool tip from data point
  1309. toolTipText = ((Annotation)obj).ReplaceKeywords(((Annotation)obj).ToolTip);
  1310. }
  1311. // Get tooltips from axis
  1312. else if (type == ChartElementType.Axis && obj != null && obj is Axis)
  1313. {
  1314. // Take tool tip from strip line
  1315. toolTipText = ((Axis)obj).ToolTip;
  1316. }
  1317. // Get tooltips from strip lines
  1318. else if (type == ChartElementType.StripLines && obj != null && obj is StripLine)
  1319. {
  1320. // Take tool tip from strip line
  1321. toolTipText = ((StripLine)obj).ToolTip;
  1322. }
  1323. // Get tooltips from data points
  1324. else if (type == ChartElementType.Title && obj != null && obj is Title)
  1325. {
  1326. // Take tool tip from data point
  1327. toolTipText = ((Title)obj).ToolTip;
  1328. } // Get tooltips for legend items
  1329. // Get tooltips for legend items
  1330. else if (type == ChartElementType.LegendItem)
  1331. {
  1332. // Take tool tip from legend item
  1333. toolTipText = ((LegendItem)obj).ToolTip;
  1334. // Check if cell has it's own tooltip
  1335. LegendCell legendCell = subObj as LegendCell;
  1336. if (legendCell != null && legendCell.ToolTip.Length > 0)
  1337. {
  1338. toolTipText = legendCell.ToolTip;
  1339. }
  1340. // Check if series is associated with legend item
  1341. if (toolTipText.Length == 0 &&
  1342. seriesName.Length > 0 &&
  1343. _chartControl.Series.IndexOf(seriesName) >= 0)
  1344. {
  1345. // Take tool tip from data point
  1346. if (dataPointIndex == -1)
  1347. {
  1348. if (seriesName.Length > 0)
  1349. {
  1350. // Take tool tip from series
  1351. toolTipText = _chartControl.Series[seriesName].ReplaceKeywords(_chartControl.Series[seriesName].LegendToolTip);
  1352. }
  1353. }
  1354. else
  1355. {
  1356. if (dataPointIndex >= 0 &&
  1357. dataPointIndex < _chartControl.Series[seriesName].Points.Count)
  1358. {
  1359. // Take tool tip from data point
  1360. toolTipText = _chartControl.Series[seriesName].Points[dataPointIndex].ReplaceKeywords(_chartControl.Series[seriesName].Points[dataPointIndex].LegendToolTip);
  1361. }
  1362. }
  1363. }
  1364. }
  1365. // Set event arguments
  1366. ToolTipEventArgs args = new ToolTipEventArgs(e.X, e.Y, toolTipText, hitTest);
  1367. // Event
  1368. _chartControl.OnGetToolTipText(args);
  1369. return args.Text.Trim();
  1370. }
  1371. /// <summary>
  1372. /// Mouse move event handler.
  1373. /// </summary>
  1374. /// <param name="sender">Sender</param>
  1375. /// <param name="e">Arguments</param>
  1376. internal void Selection_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
  1377. {
  1378. // Ignore false calls to OnMouseMove caused by the tootip control.
  1379. if (e.X == this._lastMouseMove.X && e.Y == this._lastMouseMove.Y)
  1380. {
  1381. return;
  1382. }
  1383. else
  1384. {
  1385. this._lastMouseMove.X = e.X;
  1386. this._lastMouseMove.Y = e.Y;
  1387. }
  1388. // Event is not active and tooltip properties are nor set.
  1389. if (!IsToolTipsEnabled() && !_chartControl.IsToolTipEventUsed())
  1390. {
  1391. return;
  1392. }
  1393. string newToolTipText = this.EvaluateToolTip(e);
  1394. if (!String.IsNullOrEmpty(newToolTipText))
  1395. {
  1396. string oldToolTipText = this._toolTip.GetToolTip(this._chartControl);
  1397. TimeSpan timeSpan = DateTime.Now.Subtract(this._toolTipActivationTime);
  1398. if (oldToolTipText != newToolTipText || timeSpan.Milliseconds > 600)
  1399. {
  1400. // Activate the tooltip
  1401. this._toolTip.Active = false;
  1402. this._toolTip.SetToolTip(this._chartControl, newToolTipText);
  1403. this._toolTip.Active = true;
  1404. this._toolTipActivationTime = DateTime.Now;
  1405. }
  1406. }
  1407. else
  1408. {
  1409. // We do not have a tooltip, so deactivate it
  1410. this._toolTip.Active = false;
  1411. this._toolTip.SetToolTip(this._chartControl, string.Empty);
  1412. }
  1413. }
  1414. #endregion //Tooltips
  1415. #region HitTest
  1416. /// <summary>
  1417. /// Call this method to determine the chart element,
  1418. /// if any, that is located at a point defined by the given X and Y
  1419. /// coordinates.
  1420. /// <seealso cref="HitTestResult"/></summary>
  1421. /// <param name="x">The X coordinate for the point in question.
  1422. /// Often obtained from a parameter in an event
  1423. /// (e.g. the X parameter value in the MouseDown event).</param>
  1424. /// <param name="y">The Y coordinate for the point in question.
  1425. /// Often obtained from a parameter in an event
  1426. /// (e.g. the Y parameter value in the MouseDown event).</param>
  1427. /// <param name="requestedElementTypes">
  1428. /// An array of type which specify the types
  1429. /// to test for, on order to filter the result. If omitted checking for
  1430. /// elementTypes will be ignored and all kind of elementTypes will be
  1431. /// valid.
  1432. /// </param>
  1433. /// <param name="ignoreTransparent">Indicates that transparent
  1434. /// elements should be ignored.</param>
  1435. /// <returns>
  1436. /// A array of <see cref="HitTestResult"/> objects,
  1437. /// which provides information concerning the chart element
  1438. /// (if any) that is at the specified location. Result contains at least
  1439. /// one element, which could be ChartElementType.Nothing.
  1440. /// The objects in the result are sorted in from top to bottom of
  1441. /// different layers of control. </returns>
  1442. /// <remarks>Call this method to determine the gauge element
  1443. /// (if any) that is located at a specified point. Often this method is used in
  1444. /// some mouse-related event (e.g. MouseDown)
  1445. /// to determine what gauge element the end-user clicked on.
  1446. /// The X and Y mouse coordinates obtained from the
  1447. /// event parameters are then used for the X and Y parameter
  1448. /// values of this method call. The returned
  1449. /// <see cref="HitTestResult"/> object's properties
  1450. /// can then be used to determine what chart element was clicked on,
  1451. /// and also provides a reference to the actual object selected (if
  1452. /// any).</remarks>
  1453. internal HitTestResult[] HitTest(int x, int y, bool ignoreTransparent, params ChartElementType[] requestedElementTypes)
  1454. {
  1455. List<HitTestResult> result = new List<HitTestResult>();
  1456. ArrayList regionList = this.ChartPicture.Common.HotRegionsList.List;
  1457. if (regionList.Count == 0)
  1458. {
  1459. this.ChartPicture.PaintOffScreen();
  1460. }
  1461. string alowedElements = String.Empty;
  1462. if (requestedElementTypes.Length > 0)
  1463. {
  1464. StringBuilder builder = new StringBuilder();
  1465. foreach (ChartElementType elementType in requestedElementTypes)
  1466. {
  1467. builder.Append(elementType.ToString() + ";");
  1468. }
  1469. alowedElements = builder.ToString();
  1470. }
  1471. float newX;
  1472. float newY;
  1473. float relativeX;
  1474. float relativeY;
  1475. RectangleF newMouseRect;
  1476. // Find mouse position in relative and absolute coordinates
  1477. RectangleF mouseRect = new RectangleF(x - 1, y - 1, 2, 2);
  1478. relativeX = this.Graph.GetRelativePoint(new PointF(x, y)).X;
  1479. relativeY = this.Graph.GetRelativePoint(new PointF(x, y)).Y;
  1480. RectangleF relativeMouseRect = this.Graph.GetRelativeRectangle(mouseRect);
  1481. // Try to pass through series object in design time.
  1482. // The series ussualy contain autogenerated points with short lifetime - during painting;
  1483. // This hit test result will be used in VS2005 desing time click.
  1484. for (int index = regionList.Count - 1; index >= 0; index--)
  1485. {
  1486. HotRegion region = (HotRegion)regionList[index];
  1487. // Check if only looking for specific chart element type
  1488. if (!String.IsNullOrEmpty(alowedElements) && alowedElements.IndexOf(region.Type.ToString() + ";", StringComparison.Ordinal) == -1)
  1489. {
  1490. continue;
  1491. }
  1492. // Change coordinates if relative path is used
  1493. if (region.RelativeCoordinates)
  1494. {
  1495. newX = relativeX;
  1496. newY = relativeY;
  1497. newMouseRect = relativeMouseRect;
  1498. }
  1499. else
  1500. {
  1501. newX = (float)x;
  1502. newY = (float)y;
  1503. newMouseRect = mouseRect;
  1504. }
  1505. // Check if series name and point index are valid
  1506. if (region.SeriesName.Length > 0 &&
  1507. (this.ChartControl.Series.IndexOf(region.SeriesName) < 0 || region.PointIndex >= this.ChartControl.Series[region.SeriesName].Points.Count)
  1508. )
  1509. {
  1510. continue;
  1511. }
  1512. // Check if transparent chart elements should be ignored
  1513. if (ignoreTransparent && IsElementTransparent(region))
  1514. {
  1515. continue;
  1516. }
  1517. // Check intersection with bounding rectangle
  1518. if (region.BoundingRectangle.IntersectsWith(newMouseRect))
  1519. {
  1520. bool pointVisible = false;
  1521. if (region.Path != null)
  1522. {
  1523. // If there is more then one graphical path split them and create
  1524. // image maps for every graphical path separately.
  1525. GraphicsPathIterator iterator = new GraphicsPathIterator(region.Path);
  1526. // There is more then one path.
  1527. if (iterator.SubpathCount > 1)
  1528. {
  1529. GraphicsPath subPath = new GraphicsPath();
  1530. while (iterator.NextMarker(subPath) > 0 && pointVisible == false)
  1531. {
  1532. if (subPath.IsVisible(newX, newY))
  1533. {
  1534. pointVisible = true;
  1535. }
  1536. subPath.Reset();
  1537. }
  1538. }
  1539. // There is only one path
  1540. else if (region.Path.IsVisible(newX, newY))
  1541. {
  1542. pointVisible = true;
  1543. }
  1544. }
  1545. else
  1546. {
  1547. // Point is inside bounding rectangle and path is not specified
  1548. pointVisible = true;
  1549. }
  1550. // Check if point is inside the hot region
  1551. if (pointVisible)
  1552. {
  1553. HitTestResult hitTestToAdd = this.GetHitTestResult(
  1554. region.SeriesName,
  1555. region.PointIndex,
  1556. region.Type,
  1557. region.SelectedObject,
  1558. region.SelectedSubObject
  1559. );
  1560. int elementIndex = result.FindIndex(
  1561. delegate(HitTestResult test)
  1562. {
  1563. if (
  1564. (test.ChartElementType == hitTestToAdd.ChartElementType) &&
  1565. (test.Object == hitTestToAdd.Object) &&
  1566. (test.SubObject == hitTestToAdd.SubObject) &&
  1567. (test.Series == hitTestToAdd.Series) &&
  1568. (test.PointIndex == hitTestToAdd.PointIndex)
  1569. )
  1570. {
  1571. return true;
  1572. }
  1573. return false;
  1574. }
  1575. );
  1576. if (elementIndex == -1)
  1577. {
  1578. result.Add(hitTestToAdd);
  1579. }
  1580. }
  1581. }
  1582. }
  1583. if (result.Count == 0)
  1584. {
  1585. result.Add(this.GetHitTestResult(String.Empty, 0, ChartElementType.Nothing, null, null));
  1586. }
  1587. return result.ToArray();
  1588. }
  1589. /// <summary>
  1590. /// This method performs the hit test and returns a HitTestResult objects.
  1591. /// </summary>
  1592. /// <param name="x">X coordinate</param>
  1593. /// <param name="y">Y coordinate</param>
  1594. /// <returns>Hit test result object</returns>
  1595. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
  1596. Justification = "X and Y are cartesian coordinates and well understood")]
  1597. internal HitTestResult HitTest(int x, int y)
  1598. {
  1599. return this.HitTest(x, y, false, new ChartElementType[] {})[0];
  1600. }
  1601. /// <summary>
  1602. /// This method performs the hit test and returns a HitTestResult object.
  1603. /// </summary>
  1604. /// <param name="x">X coordinate</param>
  1605. /// <param name="y">Y coordinate</param>
  1606. /// <param name="ignoreTransparent">Indicates that transparent elements should be ignored.</param>
  1607. /// <returns>Hit test result object</returns>
  1608. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
  1609. Justification = "X and Y are cartesian coordinates and well understood")]
  1610. public HitTestResult HitTest(int x, int y, bool ignoreTransparent)
  1611. {
  1612. return this.HitTest(x, y, ignoreTransparent, new ChartElementType[] { })[0];
  1613. }
  1614. /// <summary>
  1615. /// This method performs the hit test and returns a HitTestResult object.
  1616. /// </summary>
  1617. /// <param name="x">X coordinate</param>
  1618. /// <param name="y">Y coordinate</param>
  1619. /// <param name="requestedElement">Only this chart element will be hit tested.</param>
  1620. /// <returns>Hit test result object</returns>
  1621. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
  1622. Justification = "X and Y are cartesian coordinates and well understood")]
  1623. public HitTestResult HitTest(int x, int y, ChartElementType requestedElement)
  1624. {
  1625. return this.HitTest(x, y, false, requestedElement)[0];
  1626. }
  1627. /// <summary>
  1628. /// Checks if chart element associated with hot region has transparent background.
  1629. /// </summary>
  1630. /// <param name="region">Element hot region.</param>
  1631. /// <returns>True if chart element is transparent.</returns>
  1632. private bool IsElementTransparent(HotRegion region)
  1633. {
  1634. bool isTransparent = false;
  1635. if (region.Type == ChartElementType.DataPoint)
  1636. {
  1637. if (this.ChartControl != null)
  1638. {
  1639. DataPoint dataPoint = region.SelectedObject as DataPoint;
  1640. if (region.SeriesName.Length > 0)
  1641. {
  1642. dataPoint = this.ChartControl.Series[region.SeriesName].Points[region.PointIndex];
  1643. }
  1644. if (dataPoint != null && dataPoint.Color == Color.Transparent)
  1645. {
  1646. isTransparent = true;
  1647. }
  1648. }
  1649. }
  1650. else if (region.SelectedObject is Axis)
  1651. {
  1652. if (((Axis)region.SelectedObject).LineColor == Color.Transparent)
  1653. {
  1654. isTransparent = true;
  1655. }
  1656. }
  1657. else if (region.SelectedObject is ChartArea)
  1658. {
  1659. if (((ChartArea)region.SelectedObject).BackColor == Color.Transparent)
  1660. {
  1661. isTransparent = true;
  1662. }
  1663. }
  1664. else if (region.SelectedObject is Legend)
  1665. {
  1666. if (((Legend)region.SelectedObject).BackColor == Color.Transparent)
  1667. {
  1668. isTransparent = true;
  1669. }
  1670. }
  1671. else if (region.SelectedObject is Grid)
  1672. {
  1673. if (((Grid)region.SelectedObject).LineColor == Color.Transparent)
  1674. {
  1675. isTransparent = true;
  1676. }
  1677. }
  1678. else if (region.SelectedObject is StripLine)
  1679. {
  1680. if (((StripLine)region.SelectedObject).BackColor == Color.Transparent)
  1681. {
  1682. isTransparent = true;
  1683. }
  1684. }
  1685. else if (region.SelectedObject is TickMark)
  1686. {
  1687. if (((TickMark)region.SelectedObject).LineColor == Color.Transparent)
  1688. {
  1689. isTransparent = true;
  1690. }
  1691. }
  1692. else if (region.SelectedObject is Title)
  1693. {
  1694. Title title = (Title)region.SelectedObject;
  1695. if ((title.Text.Length == 0 || title.ForeColor == Color.Transparent) &&
  1696. (title.BackColor == Color.Transparent || title.BackColor.IsEmpty))
  1697. {
  1698. isTransparent = true;
  1699. }
  1700. }
  1701. return isTransparent;
  1702. }
  1703. /// <summary>
  1704. /// Returns Hit Test Result object
  1705. /// </summary>
  1706. /// <param name="seriesName">Data series Name</param>
  1707. /// <param name="pointIndex">Data point index</param>
  1708. /// <param name="type">Selected Chart element type</param>
  1709. /// <param name="obj">Selected object</param>
  1710. /// <param name="subObject">Selected sub object</param>
  1711. /// <returns>Hit test result object</returns>
  1712. [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily",
  1713. Justification = "Too large of a code change to justify making this change")]
  1714. internal HitTestResult GetHitTestResult(
  1715. string seriesName,
  1716. int pointIndex,
  1717. ChartElementType type,
  1718. object obj,
  1719. object subObject)
  1720. {
  1721. HitTestResult result = new HitTestResult();
  1722. Chart chart = this.ChartControl;
  1723. // If data point is selected convert series
  1724. // name to series object.
  1725. if (seriesName.Length > 0)
  1726. {
  1727. result.Series = chart.Series[seriesName];
  1728. }
  1729. // Selected Object
  1730. result.Object = obj;
  1731. result.SubObject = subObject;
  1732. result.PointIndex = pointIndex;
  1733. result.ChartElementType = type;
  1734. AxisScrollBar scrollBar;
  1735. switch (type)
  1736. {
  1737. case ChartElementType.Axis:
  1738. Axis axis = (Axis)obj;
  1739. result.Axis = axis;
  1740. if (axis != null)
  1741. {
  1742. result.ChartArea = axis.ChartArea;
  1743. }
  1744. break;
  1745. case ChartElementType.DataPoint:
  1746. {
  1747. if (chart.Series.IndexOf(seriesName) >= 0 &&
  1748. pointIndex < chart.Series[seriesName].Points.Count)
  1749. {
  1750. DataPoint dataPoint = chart.Series[seriesName].Points[pointIndex];
  1751. result.Axis = null;
  1752. result.ChartArea = chart.ChartAreas[dataPoint.series.ChartArea];
  1753. result.Object = dataPoint;
  1754. }
  1755. break;
  1756. }
  1757. case ChartElementType.DataPointLabel:
  1758. {
  1759. if (chart.Series.IndexOf(seriesName) >= 0 &&
  1760. pointIndex < chart.Series[seriesName].Points.Count)
  1761. {
  1762. DataPoint dataPoint = chart.Series[seriesName].Points[pointIndex];
  1763. result.Axis = null;
  1764. result.ChartArea = chart.ChartAreas[dataPoint.series.ChartArea];
  1765. result.Object = dataPoint;
  1766. }
  1767. break;
  1768. }
  1769. case ChartElementType.Gridlines:
  1770. Grid gridLines = (Grid)obj;
  1771. result.Axis = gridLines.Axis;
  1772. if (gridLines.Axis != null)
  1773. {
  1774. result.ChartArea = gridLines.Axis.ChartArea;
  1775. }
  1776. break;
  1777. case ChartElementType.LegendArea:
  1778. result.Axis = null;
  1779. result.ChartArea = null;
  1780. break;
  1781. case ChartElementType.LegendItem:
  1782. result.PointIndex = ((LegendItem)obj).SeriesPointIndex;
  1783. result.Axis = null;
  1784. result.ChartArea = null;
  1785. break;
  1786. case ChartElementType.PlottingArea:
  1787. ChartArea area = (ChartArea)obj;
  1788. result.Axis = null;
  1789. result.ChartArea = area;
  1790. break;
  1791. case ChartElementType.StripLines:
  1792. StripLine stripLines = (StripLine)obj;
  1793. result.Axis = stripLines.Axis;
  1794. if (stripLines.Axis != null)
  1795. {
  1796. result.ChartArea = stripLines.Axis.ChartArea;
  1797. }
  1798. break;
  1799. case ChartElementType.TickMarks:
  1800. TickMark tickMarks = (TickMark)obj;
  1801. result.Axis = tickMarks.Axis;
  1802. if (tickMarks.Axis != null)
  1803. {
  1804. result.ChartArea = tickMarks.Axis.ChartArea;
  1805. }
  1806. break;
  1807. case ChartElementType.Title:
  1808. result.Axis = null;
  1809. result.ChartArea = null;
  1810. break;
  1811. case ChartElementType.AxisLabels:
  1812. if (obj is CustomLabel)
  1813. {
  1814. CustomLabel label = (CustomLabel)obj;
  1815. result.Axis = label.Axis;
  1816. result.ChartArea = label.Axis!=null ? label.Axis.ChartArea : null;
  1817. }
  1818. break;
  1819. case ChartElementType.AxisLabelImage:
  1820. if (obj is CustomLabel)
  1821. {
  1822. CustomLabel label = (CustomLabel)obj;
  1823. result.Axis = label.Axis;
  1824. result.ChartArea = label.Axis!=null ? label.Axis.ChartArea : null;
  1825. }
  1826. break;
  1827. case ChartElementType.AxisTitle:
  1828. if (obj is Axis)
  1829. {
  1830. result.Axis = (Axis)obj;
  1831. result.ChartArea = result.Axis.ChartArea;
  1832. }
  1833. break;
  1834. case ChartElementType.ScrollBarLargeDecrement:
  1835. scrollBar = (AxisScrollBar)obj;
  1836. result.Axis = scrollBar.axis;
  1837. if (scrollBar.axis != null)
  1838. {
  1839. result.ChartArea = scrollBar.axis.ChartArea;
  1840. }
  1841. break;
  1842. case ChartElementType.ScrollBarLargeIncrement:
  1843. scrollBar = (AxisScrollBar)obj;
  1844. result.Axis = scrollBar.axis;
  1845. if (scrollBar.axis != null)
  1846. {
  1847. result.ChartArea = scrollBar.axis.ChartArea;
  1848. }
  1849. break;
  1850. case ChartElementType.ScrollBarSmallDecrement:
  1851. scrollBar = (AxisScrollBar)obj;
  1852. result.Axis = scrollBar.axis;
  1853. if (scrollBar.axis != null)
  1854. {
  1855. result.ChartArea = scrollBar.axis.ChartArea;
  1856. }
  1857. break;
  1858. case ChartElementType.ScrollBarSmallIncrement:
  1859. scrollBar = (AxisScrollBar)obj;
  1860. result.Axis = scrollBar.axis;
  1861. if (scrollBar.axis != null)
  1862. {
  1863. result.ChartArea = scrollBar.axis.ChartArea;
  1864. }
  1865. break;
  1866. case ChartElementType.ScrollBarThumbTracker:
  1867. scrollBar = (AxisScrollBar)obj;
  1868. result.Axis = scrollBar.axis;
  1869. if (scrollBar.axis != null)
  1870. {
  1871. result.ChartArea = scrollBar.axis.ChartArea;
  1872. }
  1873. break;
  1874. case ChartElementType.Annotation:
  1875. result.Axis = null;
  1876. result.ChartArea = null;
  1877. break;
  1878. }
  1879. return result;
  1880. }
  1881. #endregion //HitTest
  1882. #region Outline
  1883. /// <summary>
  1884. /// Gets the chart element outline.
  1885. /// </summary>
  1886. /// <param name="chartObject">The chart object.</param>
  1887. /// <param name="elementType">Type of the element.</param>
  1888. /// <returns></returns>
  1889. internal ChartElementOutline GetChartElementOutline(object chartObject, ChartElementType elementType)
  1890. {
  1891. // Check arguments
  1892. if (chartObject == null)
  1893. throw new ArgumentNullException("chartObject");
  1894. // Get outline
  1895. ChartElementOutline result = new ChartElementOutline();
  1896. chartObject = this.GetAutoGeneratedObject(chartObject);
  1897. ArrayList list = this.GetMarkers(chartObject, elementType);
  1898. result.Markers = new ReadOnlyCollection<PointF>((PointF[])list.ToArray(typeof(PointF)));
  1899. result.OutlinePath = GetGraphicsPath(list, chartObject, elementType);
  1900. return result;
  1901. }
  1902. #endregion //Outline
  1903. #region Selection
  1904. /// <summary>
  1905. /// Gets the graphics path.
  1906. /// </summary>
  1907. /// <param name="markers">The markers.</param>
  1908. /// <param name="chartObject">The chart object.</param>
  1909. /// <param name="elementType">Type of the element.</param>
  1910. /// <returns></returns>
  1911. private GraphicsPath GetGraphicsPath(IList markers, object chartObject, ChartElementType elementType)
  1912. {
  1913. bool chartArea3D = false;
  1914. ChartArea chartArea = chartObject as ChartArea;
  1915. if (chartArea != null && elementType == ChartElementType.PlottingArea)
  1916. {
  1917. chartArea3D = IsArea3D(chartArea);
  1918. }
  1919. if (elementType != ChartElementType.DataPoint &&
  1920. elementType != ChartElementType.Gridlines &&
  1921. elementType != ChartElementType.StripLines &&
  1922. elementType != ChartElementType.TickMarks &&
  1923. !chartArea3D
  1924. )
  1925. {
  1926. GraphicsPath path = new GraphicsPath();
  1927. PointF[] points = new PointF[markers.Count];
  1928. markers.CopyTo(points, 0);
  1929. if (points.Length > 3)
  1930. {
  1931. if (elementType == ChartElementType.DataPointLabel)
  1932. {
  1933. for (int i = 0; i < points.Length; i += 4)
  1934. {
  1935. RectangleF rect = RectangleF.FromLTRB(points[i].X, points[i].Y, points[i + 2].X, points[i + 2].Y);
  1936. path.Reset();
  1937. path.AddRectangle(Rectangle.Round(rect));
  1938. }
  1939. }
  1940. else
  1941. {
  1942. if (points.Length == 4)
  1943. {
  1944. Point[] pointsAlligned = new Point[points.Length];
  1945. for (int i = 0; i < points.Length; i++)
  1946. {
  1947. pointsAlligned[i] = Point.Round(points[i]);
  1948. }
  1949. path.AddPolygon(pointsAlligned);
  1950. }
  1951. else
  1952. {
  1953. path.AddPolygon(points);
  1954. }
  1955. }
  1956. }
  1957. return path;
  1958. }
  1959. return null;
  1960. }
  1961. private static Int32 GetDataPointIndex(DataPoint dataPoint)
  1962. {
  1963. int pointIndex = -1;
  1964. if (dataPoint != null && dataPoint.series != null)
  1965. {
  1966. pointIndex = dataPoint.series.Points.IndexOf(dataPoint);
  1967. if (pointIndex == -1 && dataPoint.IsCustomPropertySet("OriginalPointIndex"))
  1968. {
  1969. if (!Int32.TryParse(dataPoint.GetCustomProperty("OriginalPointIndex"), out pointIndex))
  1970. return -1;
  1971. }
  1972. }
  1973. return pointIndex;
  1974. }
  1975. /// <summary>
  1976. /// Gets the auto generated object.
  1977. /// </summary>
  1978. /// <param name="chartObject">The chart object.</param>
  1979. /// <returns></returns>
  1980. private object GetAutoGeneratedObject(object chartObject)
  1981. {
  1982. DataPoint dataPoint = chartObject as DataPoint;
  1983. if (dataPoint != null)
  1984. {
  1985. if (dataPoint.series != null)
  1986. {
  1987. string seriesName = dataPoint.series.Name;
  1988. int pointIndex = dataPoint.series.Points.IndexOf(dataPoint);
  1989. if (this.ChartControl.Series.IndexOf(seriesName) != -1)
  1990. {
  1991. Series series = this.ChartControl.Series[seriesName];
  1992. if (series.Points.Contains(dataPoint))
  1993. {
  1994. return chartObject;
  1995. }
  1996. if (pointIndex >= 0)
  1997. {
  1998. if (series.Points.Count > pointIndex)
  1999. {
  2000. return series.Points[pointIndex];
  2001. }
  2002. }
  2003. }
  2004. }
  2005. }
  2006. Series asSeries = chartObject as Series;
  2007. if (asSeries != null)
  2008. {
  2009. if (this.ChartControl.Series.Contains(asSeries))
  2010. {
  2011. return chartObject;
  2012. }
  2013. if (this.ChartControl.Series.IndexOf(asSeries.Name) != -1)
  2014. {
  2015. return this.ChartControl.Series[asSeries.Name];
  2016. }
  2017. }
  2018. return chartObject;
  2019. }
  2020. /// <summary>
  2021. /// Gets the hot regions.
  2022. /// </summary>
  2023. /// <param name="cntxObj">The CNTX obj.</param>
  2024. /// <param name="elementType">Type of the element.</param>
  2025. /// <returns></returns>
  2026. private HotRegion[] GetHotRegions(object cntxObj, ChartElementType elementType)
  2027. {
  2028. ArrayList result = new ArrayList();
  2029. HotRegionsList hrList = this.ChartPicture.Common.HotRegionsList;
  2030. string dataPointSeries = String.Empty;
  2031. int dataPointIndex = -1;
  2032. for (int i = hrList.List.Count - 1; i >= 0; i--)
  2033. {
  2034. HotRegion rgn = (HotRegion)hrList.List[i];
  2035. if (rgn.Type == elementType)
  2036. {
  2037. switch (rgn.Type)
  2038. {
  2039. case ChartElementType.LegendItem:
  2040. LegendItem legendItem = cntxObj as LegendItem;
  2041. if (legendItem != null)
  2042. {
  2043. if (((LegendItem)rgn.SelectedObject).Name == legendItem.Name)
  2044. {
  2045. result.Add(rgn);
  2046. }
  2047. }
  2048. break;
  2049. case ChartElementType.AxisLabelImage:
  2050. case ChartElementType.AxisLabels:
  2051. CustomLabel label1 = cntxObj as CustomLabel;
  2052. CustomLabel label2 = rgn.SelectedObject as CustomLabel;
  2053. if (label1 != null)
  2054. {
  2055. if (label1 != null && label2 != null)
  2056. {
  2057. if (label1.Axis == label2.Axis)
  2058. {
  2059. if (label1.FromPosition == label2.FromPosition &&
  2060. label1.ToPosition == label2.ToPosition &&
  2061. label1.RowIndex == label2.RowIndex)
  2062. {
  2063. if (rgn.Path == null)
  2064. {
  2065. result.Add(rgn);
  2066. }
  2067. }
  2068. }
  2069. }
  2070. }
  2071. else
  2072. {
  2073. Axis axis = cntxObj as Axis;
  2074. if (axis != null)
  2075. {
  2076. if (axis == label2.Axis)
  2077. {
  2078. if (rgn.Path == null)
  2079. {
  2080. result.Add(rgn);
  2081. }
  2082. }
  2083. }
  2084. }
  2085. break;
  2086. case ChartElementType.DataPointLabel:
  2087. case ChartElementType.DataPoint:
  2088. DataPoint dataPoint = cntxObj as DataPoint;
  2089. if (dataPoint != null)
  2090. {
  2091. if (String.IsNullOrEmpty(dataPointSeries) || dataPointIndex == -1)
  2092. {
  2093. dataPointSeries = dataPoint.series.Name;
  2094. dataPointIndex = GetDataPointIndex(dataPoint);
  2095. }
  2096. if (rgn.PointIndex == dataPointIndex && rgn.SeriesName == dataPointSeries)
  2097. {
  2098. result.Add(rgn);
  2099. }
  2100. }
  2101. else
  2102. {
  2103. DataPointCollection dataPointCollection = cntxObj as DataPointCollection;
  2104. if (dataPointCollection != null)
  2105. {
  2106. cntxObj = dataPointCollection.series;
  2107. }
  2108. Series series = cntxObj as Series;
  2109. if (series != null)
  2110. {
  2111. if (String.IsNullOrEmpty(dataPointSeries) || dataPointIndex == -1)
  2112. {
  2113. dataPointSeries = series.Name;
  2114. }
  2115. if (rgn.SeriesName == dataPointSeries)
  2116. {
  2117. result.Add(rgn);
  2118. }
  2119. }
  2120. }
  2121. break;
  2122. default:
  2123. if (rgn.SelectedObject == cntxObj)
  2124. {
  2125. result.Add(rgn);
  2126. }
  2127. break;
  2128. }
  2129. }
  2130. }
  2131. return (HotRegion[])result.ToArray(typeof(HotRegion));
  2132. }
  2133. /// <summary>
  2134. /// Gets the markers from regions.
  2135. /// </summary>
  2136. /// <param name="chartObject">The chart object.</param>
  2137. /// <param name="elementType">Type of the element.</param>
  2138. /// <returns></returns>
  2139. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
  2140. private ArrayList GetMarkersFromRegions(object chartObject, ChartElementType elementType)
  2141. {
  2142. ArrayList list = new ArrayList();
  2143. HotRegion[] regions = this.GetHotRegions(chartObject, elementType);
  2144. ChartGraphics graph = this.Graph;
  2145. RectangleF rect;
  2146. Grid grid = chartObject as Grid;
  2147. if (grid != null)
  2148. {
  2149. foreach (HotRegion rgn in regions)
  2150. {
  2151. if (!IsArea3D(grid.Axis.ChartArea))
  2152. {
  2153. if (IsChartAreaCircular(grid.Axis.ChartArea))
  2154. {
  2155. GraphicsPathIterator iterator = new GraphicsPathIterator(rgn.Path);
  2156. // There is more then one path.
  2157. if (iterator.SubpathCount > 1)
  2158. {
  2159. GraphicsPath subPath = new GraphicsPath();
  2160. while (iterator.NextMarker(subPath) > 0)
  2161. {
  2162. rect = subPath.GetBounds();
  2163. list.Add(new PointF(rect.Left + rect.Width / 2, rect.Top));
  2164. list.Add(new PointF(rect.Right, rect.Top + rect.Height / 2));
  2165. list.Add(new PointF(rect.Right - rect.Width / 2, rect.Bottom));
  2166. list.Add(new PointF(rect.Left, rect.Bottom - rect.Height / 2));
  2167. subPath.Reset();
  2168. }
  2169. }
  2170. }
  2171. else
  2172. {
  2173. // 2D
  2174. rect = this.GetHotRegionRectangle(rgn, RectangleF.Empty, elementType);
  2175. if (grid != null)
  2176. {
  2177. if (grid.GetAxis().AxisPosition == AxisPosition.Bottom ||
  2178. grid.GetAxis().AxisPosition == AxisPosition.Top)
  2179. {
  2180. rect.Offset(rect.Width / 2, 0);
  2181. rect.Width = 0;
  2182. }
  2183. else
  2184. {
  2185. rect.Offset(0, rect.Height / 2);
  2186. rect.Height = 0;
  2187. }
  2188. }
  2189. list.AddRange(this.GetMarkers(rect, false));
  2190. }
  2191. }
  2192. else
  2193. { // 3D
  2194. PointF[] points = rgn.Path.PathPoints;
  2195. for (int i = 0; i < points.Length - 3; i = i + 4)
  2196. { //Each gridline has a corresponding set of 4 points in the path
  2197. //One of the ends of a gridline is in the middle the line between points #0 and #3
  2198. //Another ends of a gridline is in the middle the line between points #1 and #2
  2199. //So we find those middles and put a marks to the ends of the gridline.
  2200. PointF middleP0P3 = new PointF((points[i].X + points[i + 3].X) / 2f, (points[i].Y + points[i + 3].Y) / 2f);
  2201. PointF middleP1P2 = new PointF((points[i + 1].X + points[i + 2].X) / 2f, (points[i + 1].Y + points[i + 2].Y) / 2f);
  2202. list.Add(graph.GetAbsolutePoint(middleP0P3));
  2203. list.Add(graph.GetAbsolutePoint(middleP1P2));
  2204. }
  2205. }
  2206. }
  2207. return list;
  2208. }
  2209. DataPoint dataPoint = chartObject as DataPoint;
  2210. if (dataPoint != null && elementType != ChartElementType.DataPointLabel)
  2211. {
  2212. rect = Rectangle.Empty;
  2213. Series series = dataPoint.series;
  2214. if (this.ChartControl.ChartAreas.IndexOf(series.ChartArea) == -1)
  2215. {
  2216. return list;
  2217. }
  2218. ChartArea area = this.ChartControl.ChartAreas[series.ChartArea];
  2219. PointF pp = this.Transform3D(area, dataPoint);
  2220. if (!(float.IsNaN(pp.X) || float.IsNaN(pp.Y)))
  2221. {
  2222. list.Add(graph.GetAbsolutePoint(pp));
  2223. }
  2224. return list;
  2225. }
  2226. Axis axis = chartObject as Axis;
  2227. if (axis != null && elementType == ChartElementType.AxisTitle)
  2228. {
  2229. foreach (HotRegion rgn in regions)
  2230. {
  2231. if (!IsArea3D(axis.ChartArea))
  2232. { // 2D
  2233. rect = this.GetHotRegionRectangle(rgn, RectangleF.Empty, elementType);
  2234. list.AddRange(this.GetMarkers(rect, elementType));
  2235. }
  2236. else
  2237. { // 3D
  2238. PointF[] points = rgn.Path.PathPoints;
  2239. list.AddRange(points);
  2240. }
  2241. }
  2242. return list;
  2243. }
  2244. LegendItem legendItem = chartObject as LegendItem;
  2245. if (legendItem != null)
  2246. {
  2247. rect = Rectangle.Empty;
  2248. foreach (HotRegion rgn in regions)
  2249. {
  2250. rect = this.GetHotRegionRectangle(rgn, rect, elementType);
  2251. }
  2252. if (!rect.IsEmpty)
  2253. {
  2254. list.AddRange(this.GetMarkers(rect, elementType));
  2255. }
  2256. return list;
  2257. }
  2258. else if (chartObject is Annotation)
  2259. {
  2260. rect = Rectangle.Empty;
  2261. foreach (HotRegion rgn in regions)
  2262. {
  2263. rect = this.GetHotRegionRectangle(rgn, rect, elementType);
  2264. }
  2265. if (!rect.IsEmpty)
  2266. {
  2267. list.AddRange(this.GetMarkers(rect, elementType));
  2268. }
  2269. return list;
  2270. }
  2271. foreach (HotRegion rgn in regions)
  2272. {
  2273. rect = this.GetHotRegionRectangle(rgn, RectangleF.Empty, elementType);
  2274. list.AddRange(this.GetMarkers(rect, elementType));
  2275. }
  2276. return list;
  2277. }
  2278. /// <summary>
  2279. /// Gets the markers.
  2280. /// </summary>
  2281. /// <param name="chartObject">The chart object.</param>
  2282. /// <param name="elementType">Type of the element.</param>
  2283. /// <returns></returns>
  2284. private ArrayList GetMarkers(object chartObject, ChartElementType elementType)
  2285. {
  2286. ChartArea chartArea = chartObject as ChartArea;
  2287. if (chartArea != null)
  2288. {
  2289. return this.GetAreaMarkers(this.Graph, chartArea);
  2290. }
  2291. Axis axis = chartObject as Axis;
  2292. if (axis != null)
  2293. {
  2294. if (
  2295. elementType == ChartElementType.AxisLabelImage ||
  2296. elementType == ChartElementType.AxisLabels ||
  2297. elementType == ChartElementType.AxisTitle
  2298. )
  2299. {
  2300. return this.GetMarkersFromRegions(chartObject, elementType);
  2301. }
  2302. return this.GetAxisMarkers(this.Graph, axis);
  2303. }
  2304. DataPoint dataPoint = chartObject as DataPoint;
  2305. if (dataPoint != null)
  2306. {
  2307. return this.GetMarkersFromRegions(chartObject, elementType);
  2308. }
  2309. Series series = chartObject as Series;
  2310. if (series != null)
  2311. {
  2312. if (elementType == ChartElementType.DataPointLabel)
  2313. {
  2314. return this.GetMarkersFromRegions(chartObject, elementType);
  2315. }
  2316. return this.GetSeriesMarkers(series);
  2317. }
  2318. return this.GetMarkersFromRegions(chartObject, elementType);
  2319. }
  2320. /// <summary>
  2321. /// Determines whether specified chart area is circular or not have axes. These chart areas contain pie, doughnut, polar, radar
  2322. /// </summary>
  2323. /// <param name="area">The area.</param>
  2324. /// <returns>
  2325. /// <c>true</c> if specified chart area is circular; otherwise, <c>false</c>.
  2326. /// </returns>
  2327. private Boolean IsChartAreaCircular(ChartArea area)
  2328. {
  2329. foreach (object o in area.ChartTypes)
  2330. {
  2331. ChartTypes.IChartType chartType = area.Common.ChartTypeRegistry.GetChartType(o.ToString());
  2332. if (chartType != null && (chartType.CircularChartArea || !chartType.RequireAxes))
  2333. {
  2334. return true;
  2335. }
  2336. }
  2337. return false;
  2338. }
  2339. /// <summary>
  2340. /// Determines whether the chart area is in 3D mode.
  2341. /// </summary>
  2342. /// <param name="area">The area.</param>
  2343. /// <returns>
  2344. /// <c>true</c> if the chart area is in 3D mode; otherwise, <c>false</c>.
  2345. /// </returns>
  2346. private Boolean IsArea3D(ChartArea area)
  2347. {
  2348. return area.Area3DStyle.Enable3D && !this.IsChartAreaCircular(area) && area.matrix3D != null && area.matrix3D.IsInitialized();
  2349. }
  2350. /// <summary>
  2351. /// Gets the series markers.
  2352. /// </summary>
  2353. /// <param name="series">The series.</param>
  2354. /// <returns>List of PointF.</returns>
  2355. private ArrayList GetSeriesMarkers(Series series)
  2356. {
  2357. ArrayList list = new ArrayList();
  2358. if (series != null)
  2359. {
  2360. String areaName = series.ChartArea;
  2361. if (String.IsNullOrEmpty(areaName))
  2362. {
  2363. areaName = ChartPicture.ChartAreas.DefaultNameReference;
  2364. }
  2365. if (ChartPicture.ChartAreas.IndexOf(areaName) != -1 && series.Enabled)
  2366. {
  2367. ChartArea chartArea = ChartPicture.ChartAreas[areaName];
  2368. if (ChartControl.Series.IndexOf(series.Name) != -1)
  2369. {
  2370. series = ChartControl.Series[series.Name];
  2371. }
  2372. DataPointCollection points = series.Points;
  2373. // in design mode we have usually fake points
  2374. if (points.Count == 0)
  2375. {
  2376. points = series.fakeDataPoints;
  2377. }
  2378. // transform points in 3D
  2379. foreach (DataPoint point in points)
  2380. {
  2381. PointF pp = this.Transform3D(chartArea, point);
  2382. if (float.IsNaN(pp.X) || float.IsNaN(pp.Y))
  2383. {
  2384. continue;
  2385. }
  2386. list.Add(this.Graph.GetAbsolutePoint(pp));
  2387. }
  2388. }
  2389. }
  2390. return list;
  2391. }
  2392. /// <summary>
  2393. /// Gets the axis markers - list of points where markers are drawn.
  2394. /// </summary>
  2395. /// <param name="graph">The graph.</param>
  2396. /// <param name="axis">The axis.</param>
  2397. /// <returns>List of PointF.</returns>
  2398. private ArrayList GetAxisMarkers(ChartGraphics graph, Axis axis)
  2399. {
  2400. ArrayList list = new ArrayList();
  2401. if (axis == null)
  2402. {
  2403. return list;
  2404. }
  2405. PointF first = PointF.Empty;
  2406. PointF second = PointF.Empty;
  2407. // Set the position of axis
  2408. switch (axis.AxisPosition)
  2409. {
  2410. case AxisPosition.Left:
  2411. first.X = (float)axis.GetAxisPosition();
  2412. first.Y = axis.PlotAreaPosition.Y;
  2413. second.X = (float)axis.GetAxisPosition();
  2414. second.Y = axis.PlotAreaPosition.Bottom;
  2415. first.X -= axis.labelSize + axis.markSize;
  2416. break;
  2417. case AxisPosition.Right:
  2418. first.X = (float)axis.GetAxisPosition();
  2419. first.Y = axis.PlotAreaPosition.Y;
  2420. second.X = (float)axis.GetAxisPosition();
  2421. second.Y = axis.PlotAreaPosition.Bottom;
  2422. second.X += axis.labelSize + axis.markSize;
  2423. break;
  2424. case AxisPosition.Bottom:
  2425. first.X = axis.PlotAreaPosition.X;
  2426. first.Y = (float)axis.GetAxisPosition();
  2427. second.X = axis.PlotAreaPosition.Right;
  2428. second.Y = (float)axis.GetAxisPosition();
  2429. second.Y += axis.labelSize + axis.markSize;
  2430. break;
  2431. case AxisPosition.Top:
  2432. first.X = axis.PlotAreaPosition.X;
  2433. first.Y = (float)axis.GetAxisPosition();
  2434. second.X = axis.PlotAreaPosition.Right;
  2435. second.Y = (float)axis.GetAxisPosition();
  2436. first.Y -= axis.labelSize + axis.markSize;
  2437. break;
  2438. }
  2439. // Update axis line position for circular area
  2440. if (axis.ChartArea.chartAreaIsCurcular)
  2441. {
  2442. second.Y = axis.PlotAreaPosition.Y + axis.PlotAreaPosition.Height / 2f;
  2443. }
  2444. RectangleF rect1 = new RectangleF(first.X, first.Y, second.X - first.X, second.Y - first.Y);
  2445. SizeF size = graph.GetRelativeSize(new SizeF(3, 3));
  2446. if (axis.AxisPosition == AxisPosition.Top || axis.AxisPosition == AxisPosition.Bottom)
  2447. {
  2448. rect1.Inflate(2, size.Height);
  2449. }
  2450. else
  2451. {
  2452. rect1.Inflate(size.Width, 2);
  2453. }
  2454. IList list1 = this.GetMarkers(rect1, ChartElementType.Axis);
  2455. ChartArea area = axis.ChartArea;
  2456. if (this.IsArea3D(area))
  2457. {
  2458. Boolean axisOnEdge = false;
  2459. float zPositon = axis.GetMarksZPosition(out axisOnEdge);
  2460. // Transform coordinates
  2461. Point3D[] points = new Point3D[list1.Count];
  2462. for (int i = 0; i < list1.Count; i++)
  2463. {
  2464. points[i] = new Point3D(((PointF)list1[i]).X, ((PointF)list1[i]).Y, zPositon);
  2465. }
  2466. axis.ChartArea.matrix3D.TransformPoints(points);
  2467. for (int i = 0; i < list1.Count; i++)
  2468. {
  2469. list1[i] = points[i].PointF;
  2470. }
  2471. }
  2472. foreach (PointF p in list1)
  2473. {
  2474. list.Add(graph.GetAbsolutePoint(p));
  2475. }
  2476. return list;
  2477. }
  2478. /// <summary>
  2479. /// Gets the area markers.
  2480. /// </summary>
  2481. /// <param name="graph">The graph.</param>
  2482. /// <param name="area">The area.</param>
  2483. /// <returns>List of PointF.</returns>
  2484. private ArrayList GetAreaMarkers(ChartGraphics graph, ChartArea area)
  2485. {
  2486. ArrayList list = new ArrayList();
  2487. if (area == null)
  2488. {
  2489. return list;
  2490. }
  2491. IList list1 = this.GetMarkers(area.PlotAreaPosition.ToRectangleF(), ChartElementType.PlottingArea);
  2492. if (this.IsChartAreaCircular(area))
  2493. {
  2494. list1 = this.GetMarkers(area.lastAreaPosition, ChartElementType.PlottingArea);
  2495. }
  2496. if (IsArea3D(area))
  2497. {
  2498. float zPositon = 0; // area.areaSceneDepth;
  2499. // Transform coordinates
  2500. Point3D[] points = new Point3D[list1.Count];
  2501. for (int i = 0; i < list1.Count; i++)
  2502. {
  2503. points[i] = new Point3D(((PointF)list1[i]).X, ((PointF)list1[i]).Y, zPositon);
  2504. }
  2505. area.matrix3D.TransformPoints(points);
  2506. for (int i = 0; i < list1.Count; i++)
  2507. {
  2508. list1[i] = points[i].PointF;
  2509. }
  2510. }
  2511. foreach (PointF p in list1)
  2512. {
  2513. list.Add(graph.GetAbsolutePoint(p));
  2514. }
  2515. return list;
  2516. }
  2517. /// <summary>
  2518. /// Builds list of markers (PointF) based on rectangle
  2519. /// </summary>
  2520. /// <param name="rect">The rectangle</param>
  2521. /// <param name="elementType">The type of chart elements to retrieve.</param>
  2522. /// <returns>List of PointF</returns>
  2523. private ArrayList GetMarkers(RectangleF rect, ChartElementType elementType)
  2524. {
  2525. if (elementType.ToString().StartsWith("Legend", StringComparison.Ordinal) || elementType.ToString().StartsWith("Title", StringComparison.Ordinal))
  2526. {
  2527. rect.Inflate(4f, 4f);
  2528. }
  2529. if (elementType.ToString().StartsWith("PlottingArea", StringComparison.Ordinal))
  2530. {
  2531. SizeF relSize = this.Graph.GetRelativeSize(new SizeF(4f, 4f));
  2532. rect.Inflate(relSize.Width, relSize.Height);
  2533. }
  2534. if ((elementType != ChartElementType.Nothing) && (elementType != ChartElementType.PlottingArea))
  2535. {
  2536. return this.GetMarkers(rect, false);
  2537. }
  2538. return this.GetMarkers(rect, true);
  2539. }
  2540. /// <summary>
  2541. /// Builds list of markers (PointF) based on rectangle
  2542. /// </summary>
  2543. /// <param name="rect">The rectangle</param>
  2544. /// <param name="addAdditionalMarkers">Add additional markers to the rectangle.</param>
  2545. /// <returns>List of PointF</returns>
  2546. private ArrayList GetMarkers(RectangleF rect, Boolean addAdditionalMarkers)
  2547. {
  2548. ArrayList list = new ArrayList();
  2549. if (!addAdditionalMarkers)
  2550. {
  2551. if (rect.Width > 0 && rect.Height > 0)
  2552. {
  2553. list.Add(new PointF(rect.Left, rect.Top));
  2554. list.Add(new PointF(rect.Right, rect.Top));
  2555. list.Add(new PointF(rect.Right, rect.Bottom));
  2556. list.Add(new PointF(rect.Left, rect.Bottom));
  2557. }
  2558. else if (rect.Width > 0)
  2559. {
  2560. list.Add(new PointF(rect.Left, rect.Top));
  2561. list.Add(new PointF(rect.Right, rect.Top));
  2562. }
  2563. else if (rect.Height > 0)
  2564. {
  2565. list.Add(new PointF(rect.Left, rect.Top));
  2566. list.Add(new PointF(rect.Left, rect.Bottom));
  2567. }
  2568. }
  2569. else
  2570. {
  2571. if (rect.Width > 0)
  2572. {
  2573. list.Add(new PointF(rect.Left, rect.Top));
  2574. if (rect.Width > 30)
  2575. {
  2576. list.Add(new PointF(rect.Left + rect.Width / 2, rect.Top));
  2577. }
  2578. list.Add(new PointF(rect.Right, rect.Top));
  2579. if (rect.Height > 30)
  2580. {
  2581. list.Add(new PointF(rect.Right, rect.Top + rect.Height / 2));
  2582. }
  2583. list.Add(new PointF(rect.Right, rect.Bottom));
  2584. if (rect.Width > 30)
  2585. {
  2586. list.Add(new PointF(rect.Left + rect.Width / 2, rect.Bottom));
  2587. }
  2588. list.Add(new PointF(rect.Left, rect.Bottom));
  2589. if (rect.Height > 30)
  2590. {
  2591. list.Add(new PointF(rect.Left, rect.Top + rect.Height / 2));
  2592. }
  2593. }
  2594. else if (rect.Width > 0)
  2595. {
  2596. list.Add(new PointF(rect.Left, rect.Top));
  2597. if (rect.Width > 30)
  2598. {
  2599. list.Add(new PointF(rect.Left + rect.Width / 2, rect.Top));
  2600. }
  2601. list.Add(new PointF(rect.Right, rect.Top));
  2602. }
  2603. else if (rect.Height > 0)
  2604. {
  2605. list.Add(new PointF(rect.Left, rect.Bottom));
  2606. if (rect.Height > 30)
  2607. {
  2608. list.Add(new PointF(rect.Left, rect.Top + rect.Height / 2));
  2609. }
  2610. list.Add(new PointF(rect.Left, rect.Top));
  2611. }
  2612. }
  2613. return list;
  2614. }
  2615. /// <summary>
  2616. /// Gets the region markers from graphics path.
  2617. /// </summary>
  2618. /// <param name="path">The path.</param>
  2619. /// <returns>List of PointF.</returns>
  2620. private ArrayList GetRegionMarkers(GraphicsPath path)
  2621. {
  2622. return new ArrayList(path.PathPoints);
  2623. }
  2624. /// <summary>
  2625. /// Calculates a DataPoint of 3D area into PointF to draw.
  2626. /// </summary>
  2627. /// <param name="chartArea">3D chart area</param>
  2628. /// <param name="point">The DataPoint</param>
  2629. /// <returns>Calculated PointF</returns>
  2630. private PointF Transform3D(ChartArea chartArea, DataPoint point)
  2631. {
  2632. if (chartArea is ChartArea && IsArea3D(chartArea))
  2633. {
  2634. // Get anotation Z coordinate (use scene depth or anchored point Z position)
  2635. float positionZ = chartArea.areaSceneDepth;
  2636. if (point != null && point.series != null)
  2637. {
  2638. float depth = 0f;
  2639. chartArea.GetSeriesZPositionAndDepth(
  2640. point.series,
  2641. out depth,
  2642. out positionZ);
  2643. positionZ += depth / 2f;
  2644. }
  2645. PointF pf = point.positionRel;
  2646. // Define 3D points of annotation object
  2647. Point3D[] annot3DPoints = new Point3D[1];
  2648. annot3DPoints[0] = new Point3D(pf.X, pf.Y, positionZ);
  2649. // Tranform cube coordinates
  2650. chartArea.matrix3D.TransformPoints(annot3DPoints);
  2651. return annot3DPoints[0].PointF;
  2652. }
  2653. return point.positionRel;
  2654. }
  2655. /// <summary>
  2656. /// Gets the hot region rectangle.
  2657. /// </summary>
  2658. /// <param name="rgn">The hot region.</param>
  2659. /// <param name="unionWith">The rectangle to union with.</param>
  2660. /// <param name="elementType">The type of the element.</param>
  2661. /// <returns>Returns the rectangle around the hot region.</returns>
  2662. private RectangleF GetHotRegionRectangle(HotRegion rgn, RectangleF unionWith, ChartElementType elementType)
  2663. {
  2664. RectangleF rect;
  2665. if (rgn.Path != null)
  2666. {
  2667. rect = rgn.Path.GetBounds();
  2668. }
  2669. else
  2670. {
  2671. rect = rgn.BoundingRectangle;
  2672. }
  2673. if (rgn.RelativeCoordinates)
  2674. {
  2675. rect = this.Graph.GetAbsoluteRectangle(rect);
  2676. }
  2677. if (elementType == ChartElementType.AxisLabels)
  2678. {
  2679. if (rect.Width > rect.Height)
  2680. {
  2681. rect.Inflate(-5, -2);
  2682. }
  2683. else if (rect.Width < rect.Height)
  2684. {
  2685. rect.Inflate(-2, -5);
  2686. }
  2687. }
  2688. if (!unionWith.IsEmpty)
  2689. {
  2690. return RectangleF.Union(unionWith, rect);
  2691. }
  2692. return rect;
  2693. }
  2694. #endregion //Selection
  2695. #endregion //Tooltips
  2696. #region IServiceProvider Members
  2697. /// <summary>
  2698. /// Gets the service object of the specified type.
  2699. /// </summary>
  2700. /// <param name="serviceType">An object that specifies the type of service object to get.</param>
  2701. /// <returns>
  2702. /// A service object of type <paramref name="serviceType"/>. It returns null
  2703. /// if there is no service object of type <paramref name="serviceType"/>.
  2704. /// </returns>
  2705. object IServiceProvider.GetService(Type serviceType)
  2706. {
  2707. if (serviceType == typeof(Selection))
  2708. {
  2709. return this;
  2710. }
  2711. if (_service != null)
  2712. {
  2713. return _service.GetService(serviceType);
  2714. }
  2715. return null;
  2716. }
  2717. #endregion
  2718. }
  2719. /// <summary>
  2720. /// The ToolTipEventArgs class stores the tool tips event arguments.
  2721. /// </summary>
  2722. public class ToolTipEventArgs : EventArgs
  2723. {
  2724. #region Private fields
  2725. // Private fields for properties values storage
  2726. private int x = 0;
  2727. private int y = 0;
  2728. private string text = "";
  2729. private HitTestResult result = new HitTestResult();
  2730. #endregion
  2731. #region Constructors
  2732. /// <summary>
  2733. /// ToolTipEventArgs constructor. Creates ToolTip event arguments.
  2734. /// </summary>
  2735. /// <param name="x">X-coordinate of mouse.</param>
  2736. /// <param name="y">Y-coordinate of mouse.</param>
  2737. /// <param name="text">Tooltip text.</param>
  2738. /// <param name="result">Hit test result object.</param>
  2739. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
  2740. Justification = "X and Y are cartesian coordinates and well understood")]
  2741. public ToolTipEventArgs(int x, int y, string text, HitTestResult result)
  2742. {
  2743. this.x = x;
  2744. this.y = y;
  2745. this.text = text;
  2746. this.result = result;
  2747. }
  2748. #endregion
  2749. #region Properties
  2750. /// <summary>
  2751. /// Gets the x-coordinate of the mouse.
  2752. /// </summary>
  2753. [
  2754. SRDescription("DescriptionAttributeToolTipEventArgs_X"),
  2755. ]
  2756. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "X")]
  2757. public int X
  2758. {
  2759. get
  2760. {
  2761. return x;
  2762. }
  2763. }
  2764. /// <summary>
  2765. /// Gets the result of the hit test.
  2766. /// </summary>
  2767. [
  2768. SRDescription("DescriptionAttributeToolTipEventArgs_HitTestResult"),
  2769. ]
  2770. public HitTestResult HitTestResult
  2771. {
  2772. get
  2773. {
  2774. return result;
  2775. }
  2776. }
  2777. /// <summary>
  2778. /// Gets the y-coordinate of the mouse.
  2779. /// </summary>
  2780. [
  2781. SRDescription("DescriptionAttributeToolTipEventArgs_Y"),
  2782. ]
  2783. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Y")]
  2784. public int Y
  2785. {
  2786. get
  2787. {
  2788. return y;
  2789. }
  2790. }
  2791. /// <summary>
  2792. /// Gets the text of the tooltip.
  2793. /// </summary>
  2794. [
  2795. SRDescription("DescriptionAttributeToolTipEventArgs_Text"),
  2796. ]
  2797. public string Text
  2798. {
  2799. get
  2800. {
  2801. return text;
  2802. }
  2803. set
  2804. {
  2805. text = value;
  2806. }
  2807. }
  2808. #endregion
  2809. }
  2810. }