12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197 |
- // Licensed to the .NET Foundation under one or more agreements.
- // The .NET Foundation licenses this file to you under the MIT license.
- // See the LICENSE file in the project root for more information.
- //
- // Purpose: This file contains methods used for Win Form selection
- //
- using System;
- using System.Windows.Forms;
- using System.Collections;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.ComponentModel.Design;
- using System.Diagnostics.CodeAnalysis;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Globalization;
- using System.Text;
- namespace FastReport.DataVisualization.Charting
- {
- using Point = System.Drawing.Point;
- #region Enumerations
- // Plase keep the folowing enumaration in chart layering order - ex. ChartArea is under DataPoint
- /// <summary>
- /// An enumeration of types of Chart Element.
- /// </summary>
- public enum ChartElementType
- {
- /// <summary>
- /// No chart element.
- /// </summary>
- Nothing,
- /// <summary>
- /// The title of a chart.
- /// </summary>
- Title,
- /// <summary>
- /// Plotting area (chart area excluding axes, labels, etc.).
- /// Also excludes the regions that data points may occupy.
- /// </summary>
- PlottingArea,
- /// <summary>
- /// An Axis object.
- /// </summary>
- Axis,
- /// <summary>
- /// Any major or minor tick mark.
- /// </summary>
- TickMarks,
- /// <summary>
- /// Any major or minor grid line (both vertical or horizontal).
- /// </summary>
- Gridlines,
- /// <summary>
- /// A StripLine object.
- /// </summary>
- StripLines,
- /// <summary>
- /// Axis label Image.
- /// </summary>
- AxisLabelImage,
- /// <summary>
- /// Axis labels
- /// </summary>
- AxisLabels,
- /// <summary>
- /// Axis title
- /// </summary>
- AxisTitle,
- /// <summary>
- /// A scrollbar tracking thumb.
- /// </summary>
- ScrollBarThumbTracker,
- /// <summary>
- /// A scrollbar small decrement button. A "down arrow"
- /// button for a vertical scrollbar, or a "left arrow"
- /// button for a horizontal scroll bar.
- /// </summary>
- ScrollBarSmallDecrement,
- /// <summary>
- /// A scrollbar small increment button. An "up arrow"
- /// button for a vertical scrollbar, or a "right arrow"
- /// button for a horizontal scroll bar.
- /// </summary>
- ScrollBarSmallIncrement,
- /// <summary>
- /// The background of a scrollbar that will result in
- /// a large decrement in the scale view size when clicked.
- /// This is the background below the thumb for
- /// a vertical scrollbar, and to the left of
- /// the thumb for a horizontal scrollbar.
- /// </summary>
- ScrollBarLargeDecrement,
- /// <summary>
- /// The background of a scrollbar that will result in
- /// a large increment in the scale view size when clicked.
- /// This is the background above the thumb for
- /// a vertical scrollbar, and to the right of
- /// the thumb for a horizontal scrollbar.
- /// </summary>
- ScrollBarLargeIncrement,
- /// <summary>
- /// The zoom reset button of a scrollbar.
- /// </summary>
- ScrollBarZoomReset,
- /// <summary>
- /// A DataPoint object.
- /// </summary>
- DataPoint,
- /// <summary>
- /// Series data point label.
- /// </summary>
- DataPointLabel,
- /// <summary>
- /// The area inside a Legend object. Does not include
- /// the space occupied by legend items.
- /// </summary>
- LegendArea,
- /// <summary>
- /// Legend title.
- /// </summary>
- LegendTitle,
- /// <summary>
- /// Legend header.
- /// </summary>
- LegendHeader,
- /// <summary>
- /// A LegendItem object.
- /// </summary>
- LegendItem,
- /// <summary>
- /// Chart annotation object.
- /// </summary>
- Annotation,
- }
- /// <summary>
- /// Enumeration (Flag) used for processing chart types.
- /// </summary>
- [Flags]
- internal enum ProcessMode
- {
- /// <summary>
- /// Paint mode
- /// </summary>
- Paint = 1,
- /// <summary>
- /// Selection mode. Collection of hot regions has to be created.
- /// </summary>
- HotRegions = 2,
- /// <summary>
- /// Used for image maps
- /// </summary>
- ImageMaps = 4
- }
- #endregion
- /// <summary>
- /// This class presents item in
- /// the collection of hot regions.
- /// </summary>
- internal class HotRegion : IDisposable
- {
- #region Fields
- // Private data members, which store properties values
- private GraphicsPath _path = null;
- private bool _relativeCoordinates = true;
- private RectangleF _boundingRectangle = RectangleF.Empty;
- private object _selectedObject = null;
- private int _pointIndex = -1;
- private string _seriesName = "";
- private ChartElementType _type = ChartElementType.Nothing;
- private object _selectedSubObject = null;
- #endregion // Fields
- #region Properties
- /// <summary>
- /// Region is Graphics path
- /// </summary>
- internal GraphicsPath Path
- {
- get
- {
- return _path;
- }
- set
- {
- _path = value;
- }
- }
- /// <summary>
- /// Relative coordinates are used
- /// to define region
- /// </summary>
- internal bool RelativeCoordinates
- {
- get
- {
- return _relativeCoordinates;
- }
- set
- {
- _relativeCoordinates = value;
- }
- }
- /// <summary>
- /// Bounding Rectangle of an shape
- /// </summary>
- internal RectangleF BoundingRectangle
- {
- get
- {
- return _boundingRectangle;
- }
- set
- {
- _boundingRectangle = value;
- }
- }
- /// <summary>
- /// Object which is presented with this region
- /// </summary>
- internal object SelectedObject
- {
- get
- {
- return _selectedObject;
- }
- set
- {
- _selectedObject = value;
- }
- }
- /// <summary>
- /// Sub-Object which is presented with this region
- /// </summary>
- internal object SelectedSubObject
- {
- get
- {
- return _selectedSubObject;
- }
- set
- {
- _selectedSubObject = value;
- }
- }
- /// <summary>
- /// Index of the data point which is presented with this region
- /// </summary>
- internal int PointIndex
- {
- get
- {
- return _pointIndex;
- }
- set
- {
- _pointIndex = value;
- }
- }
- /// <summary>
- /// Name of the series which is presented with the region
- /// </summary>
- internal string SeriesName
- {
- get
- {
- return _seriesName;
- }
- set
- {
- _seriesName = value;
- }
- }
- /// <summary>
- /// Chart Element AxisName
- /// </summary>
- internal ChartElementType Type
- {
- get
- {
- return _type;
- }
- set
- {
- _type = value;
- }
- }
- #endregion // Properties
- #region IDisposable members
- /// <summary>
- /// Releases unmanaged and - optionally - managed resources
- /// </summary>
- /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (_path != null)
- {
- _path.Dispose();
- _path = null;
- }
- }
- }
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- #endregion
- #region Methods
-
- /// <summary>
- /// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
- /// </summary>
- /// <returns>
- /// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
- /// </returns>
- public override string ToString()
- {
- string objectType = this.SelectedObject != null ? this.SelectedObject.ToString() : "null";
- if (this.SelectedObject == null && !String.IsNullOrEmpty(this.SeriesName))
- {
- objectType = this.SeriesName;
- }
- return String.Format(CultureInfo.CurrentCulture, "{0} of {1}", this.Type, objectType);
- }
- #endregion //Methods
- }
- /// <summary>
- /// This class is used to fill and
- /// manage collection with Hot Regions
- /// </summary>
- internal class HotRegionsList : IDisposable
- {
- #region Fields
- /// <summary>
- /// Process chart mode Flag
- /// </summary>
- private ProcessMode _processChartMode = ProcessMode.Paint;
- /// <summary>
- /// Collection with Hor Region Elements
- /// </summary>
- private System.Collections.ArrayList _regionList = new ArrayList();
- /// <summary>
- /// Reference to the common elements object
- /// </summary>
- private CommonElements _common = null;
- /// <summary>
- /// True if hit test function is called
- /// </summary>
- internal bool hitTestCalled = false;
- #endregion // Fields
- #region Properties
- /// <summary>
- /// Flag used for processing chart types. It could
- /// be Paint, HotRegion or both mode.
- /// </summary>
- internal ProcessMode ProcessChartMode
- {
- get
- {
- return _processChartMode;
- }
- set
- {
- _processChartMode = value;
- if(this._common != null)
- {
- this._common.processModePaint =
- (_processChartMode & ProcessMode.Paint ) == ProcessMode.Paint;
- this._common.processModeRegions =
- ( _processChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions ||
- ( _processChartMode & ProcessMode.ImageMaps ) == ProcessMode.ImageMaps;
- }
- }
- }
- /// <summary>
- /// Collection with Hor Region Elements
- /// </summary>
- internal ArrayList List
- {
- get
- {
- return _regionList;
- }
- }
- #endregion // Properties
- #region Methods
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="common">Reference to the CommonElements</param>
- internal HotRegionsList( CommonElements common )
- {
- this._common = common;
- }
- /// <summary>
- /// Add hot region to the collection.
- /// </summary>
- /// <param name="rectSize">Rectangle which presents an Hot Region</param>
- /// <param name="point">Data Point</param>
- /// <param name="seriesName">Data Series</param>
- /// <param name="pointIndex">Index of an Data Point in the series</param>
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
- public void AddHotRegion(
- RectangleF rectSize,
- DataPoint point,
- string seriesName,
- int pointIndex
- )
- {
- if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
- {
- HotRegion region = new HotRegion();
-
- region.BoundingRectangle = rectSize;
- region.SeriesName = seriesName;
- region.PointIndex = pointIndex;
- region.Type = ChartElementType.DataPoint;
- region.RelativeCoordinates = true;
- // Use index of the original data point
- if(point != null && point.IsCustomPropertySet("OriginalPointIndex"))
- {
- region.PointIndex = int.Parse(point["OriginalPointIndex"], CultureInfo.InvariantCulture);
- }
-
- _regionList.Add( region );
- }
- }
- /// <summary>
- /// Adds the hot region.
- /// </summary>
- /// <param name="path">Bounding GraphicsPath.</param>
- /// <param name="relativePath">if set to <c>true</c> the is relative path.</param>
- /// <param name="graph">Chart Graphics Object</param>
- /// <param name="point">Selected data point</param>
- /// <param name="seriesName">Name of the series.</param>
- /// <param name="pointIndex">Index of the point.</param>
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "graph")]
- internal void AddHotRegion(
- GraphicsPath path,
- bool relativePath,
- ChartGraphics graph,
- DataPoint point,
- string seriesName,
- int pointIndex
- )
- {
- if( path == null )
- {
- return;
- }
- if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
- {
-
- HotRegion region = new HotRegion();
-
- region.SeriesName = seriesName;
- region.PointIndex = pointIndex;
- region.Type = ChartElementType.DataPoint;
- region.Path = (GraphicsPath)path.Clone();
- region.BoundingRectangle = path.GetBounds();
- region.RelativeCoordinates = relativePath;
- // Use index of the original data point
- if(point != null && point.IsCustomPropertySet("OriginalPointIndex"))
- {
- region.PointIndex = int.Parse(point["OriginalPointIndex"], CultureInfo.InvariantCulture);
- }
-
- _regionList.Add( region );
- }
- }
- /// <summary>
- /// Adds the hot region.
- /// </summary>
- /// <param name="insertIndex">Position where to insert element. Used for image maps only</param>
- /// <param name="path">Bounding GraphicsPath.</param>
- /// <param name="relativePath">if set to <c>true</c> the is relative path.</param>
- /// <param name="graph">Chart Graphics Object</param>
- /// <param name="point">Selected data point</param>
- /// <param name="seriesName">Name of the series.</param>
- /// <param name="pointIndex">Index of the point.</param>
- [
- System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "graph"),
- System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "insertIndex")
- ]
- internal void AddHotRegion(
- int insertIndex,
- GraphicsPath path,
- bool relativePath,
- ChartGraphics graph,
- DataPoint point,
- string seriesName,
- int pointIndex
- )
- {
- if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
- {
-
- HotRegion region = new HotRegion();
-
- region.SeriesName = seriesName;
- region.PointIndex = pointIndex;
- region.Type = ChartElementType.DataPoint;
- region.Path = (GraphicsPath)path.Clone();
- region.BoundingRectangle = path.GetBounds();
- region.RelativeCoordinates = relativePath;
- // Use index of the original data point
- if(point != null && point.IsCustomPropertySet("OriginalPointIndex"))
- {
- region.PointIndex = int.Parse(point["OriginalPointIndex"], CultureInfo.InvariantCulture);
- }
-
- _regionList.Add( region );
- }
- }
- /// <summary>
- /// Add hot region to the collection.
- /// </summary>
- /// <param name="path">Graphics path which presents hot region</param>
- /// <param name="relativePath">Graphics path uses relative or absolute coordinates</param>
- /// <param name="coord">Coordinates which defines polygon (Graphics Path). Used for image maps</param>
- /// <param name="point">Selected data point</param>
- /// <param name="seriesName">Data Series</param>
- /// <param name="pointIndex">Index of an Data Point in the series</param>
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "coord")]
- internal void AddHotRegion( GraphicsPath path, bool relativePath, float [] coord, DataPoint point, string seriesName, int pointIndex )
- {
- if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
- {
-
- HotRegion region = new HotRegion();
-
- region.SeriesName = seriesName;
- region.PointIndex = pointIndex;
- region.Type = ChartElementType.DataPoint;
- region.Path = (GraphicsPath)path.Clone();
- region.BoundingRectangle = path.GetBounds();
- region.RelativeCoordinates = relativePath;
- // Use index of the original data point
- if(point != null && point.IsCustomPropertySet("OriginalPointIndex"))
- {
- region.PointIndex = int.Parse(point["OriginalPointIndex"], CultureInfo.InvariantCulture);
- }
-
- _regionList.Add( region );
- }
- }
- /// <summary>
- /// Add Hot region to the collection.
- /// </summary>
- /// <param name="insertIndex">Position where to insert element. Used for image maps only</param>
- /// <param name="graph">Chart Graphics Object</param>
- /// <param name="x">x coordinate.</param>
- /// <param name="y">y coordinate.</param>
- /// <param name="radius">The radius.</param>
- /// <param name="point">Selected data point</param>
- /// <param name="seriesName">Data Series</param>
- /// <param name="pointIndex">Index of an Data Point in the series</param>
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "insertIndex")]
- internal void AddHotRegion( int insertIndex, ChartGraphics graph, float x, float y, float radius, DataPoint point, string seriesName, int pointIndex )
- {
- if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
- {
- HotRegion region = new HotRegion();
- PointF circleCenter = graph.GetAbsolutePoint( new PointF( x, y ) );
- SizeF circleRadius = graph.GetAbsoluteSize( new SizeF( radius, radius ) );
- GraphicsPath path = new GraphicsPath();
- path.AddEllipse(
- circleCenter.X - circleRadius.Width,
- circleCenter.Y - circleRadius.Width,
- 2 * circleRadius.Width,
- 2 * circleRadius.Width
- );
- region.BoundingRectangle = path.GetBounds();
- region.SeriesName = seriesName;
- region.Type = ChartElementType.DataPoint;
- region.PointIndex = pointIndex;
- region.Path = path;
- region.RelativeCoordinates = false;
- // Use index of the original data point
- if(point != null && point.IsCustomPropertySet("OriginalPointIndex"))
- {
- region.PointIndex = int.Parse(point["OriginalPointIndex"], CultureInfo.InvariantCulture);
- }
- _regionList.Add( region );
- }
- }
- /// <summary>
- /// Add Hot region to the collection.
- /// </summary>
- /// <param name="rectArea">Hot Region rectangle</param>
- /// <param name="toolTip">Tool Tip Text</param>
- /// <param name="hRef">HRef string</param>
- /// <param name="mapAreaAttributes">Map area Attribute string</param>
- /// <param name="postBackValue">The post back value associated with this item</param>
- /// <param name="selectedObject">Object which present hot region</param>
- /// <param name="type">AxisName of the object which present hot region</param>
- /// <param name="series">Selected series</param>
- [
- System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "hRef"),
- System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "mapAreaAttributes"),
- System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "postBackValue"),
- System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "toolTip")
- ]
- internal void AddHotRegion( RectangleF rectArea, string toolTip, string hRef, string mapAreaAttributes, string postBackValue, object selectedObject, ChartElementType type, string series )
- {
- if ( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
- {
- HotRegion region = new HotRegion();
-
- region.BoundingRectangle = rectArea;
- region.RelativeCoordinates = true;
- region.Type = type;
- region.SelectedObject = selectedObject;
- if(!String.IsNullOrEmpty(series))
- {
- region.SeriesName = series;
- }
- _regionList.Add( region );
- }
- }
- /// <summary>
- /// Add Hot region to the collection.
- /// </summary>
- /// <param name="rectArea">Hot Region rectangle</param>
- /// <param name="toolTip">Tool Tip Text</param>
- /// <param name="hRef">HRef string</param>
- /// <param name="mapAreaAttributes">Map area Attribute string</param>
- /// <param name="postBackValue">The post back value associated with this item</param>
- /// <param name="selectedObject">Object which present hot region</param>
- /// <param name="selectedSubObject">Sub-Object which present hot region</param>
- /// <param name="type">AxisName of the object which present hot region</param>
- /// <param name="series">Selected series</param>
- [
- System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "hRef"),
- System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "mapAreaAttributes"),
- System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "postBackValue"),
- System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "toolTip")
- ]
- internal void AddHotRegion(
- RectangleF rectArea,
- string toolTip,
- string hRef,
- string mapAreaAttributes,
- string postBackValue,
- object selectedObject,
- object selectedSubObject,
- ChartElementType type,
- string series )
- {
- if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
- {
- HotRegion region = new HotRegion();
-
- region.BoundingRectangle = rectArea;
- region.RelativeCoordinates = true;
- region.Type = type;
- region.SelectedObject = selectedObject;
- region.SelectedSubObject = selectedSubObject;
- if(!String.IsNullOrEmpty(series))
- {
- region.SeriesName = series;
- }
- _regionList.Add( region );
- }
- }
- /// <summary>
- /// Add Hot region to the collection.
- /// </summary>
- /// <param name="graph">Chart Graphics Object</param>
- /// <param name="path">Graphics path</param>
- /// <param name="relativePath">Used relative coordinates for graphics path.</param>
- /// <param name="toolTip">Tool Tip Text</param>
- /// <param name="hRef">HRef string</param>
- /// <param name="mapAreaAttributes">Map area Attribute string</param>
- /// <param name="postBackValue">The post back value associated with this item</param>
- /// <param name="selectedObject">Object which present hot region</param>
- /// <param name="type">AxisName of the object which present hot region</param>
- [
- System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "graph"),
- System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "hRef"),
- System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "mapAreaAttributes"),
- System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "postBackValue"),
- System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "toolTip")
- ]
- internal void AddHotRegion( ChartGraphics graph, GraphicsPath path, bool relativePath, string toolTip, string hRef, string mapAreaAttributes, string postBackValue, object selectedObject, ChartElementType type )
- {
- if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
- {
-
- HotRegion region = new HotRegion();
-
- region.Type = type;
- region.Path = (GraphicsPath)path.Clone();
- region.SelectedObject = selectedObject;
- region.BoundingRectangle = path.GetBounds();
- region.RelativeCoordinates = relativePath;
- _regionList.Add( region );
- }
- }
- /// <summary>
- /// Add Hot region to the collection.
- /// </summary>
- /// <param name="rectArea">Hot Region rectangle</param>
- /// <param name="selectedObject">Object which present hot region</param>
- /// <param name="type">AxisName of the object which present hot region</param>
- /// <param name="relativeCoordinates">Coordinates for rectangle are relative</param>
- internal void AddHotRegion( RectangleF rectArea, object selectedObject, ChartElementType type, bool relativeCoordinates )
- {
- this.AddHotRegion( rectArea, selectedObject, type, relativeCoordinates, false );
- }
- /// <summary>
- /// Add Hot region to the collection.
- /// </summary>
- /// <param name="rectArea">Hot Region rectangle</param>
- /// <param name="selectedObject">Object which present hot region</param>
- /// <param name="type">AxisName of the object which present hot region</param>
- /// <param name="relativeCoordinates">Coordinates for rectangle are relative</param>
- /// <param name="insertAtBeginning">Insert the hot region at the beginning of the collection</param>
- internal void AddHotRegion( RectangleF rectArea, object selectedObject, ChartElementType type, bool relativeCoordinates, bool insertAtBeginning )
- {
- if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
- {
- HotRegion region = new HotRegion();
-
- region.BoundingRectangle = rectArea;
- region.RelativeCoordinates = relativeCoordinates;
- region.Type = type;
- region.SelectedObject = selectedObject;
-
- if( insertAtBeginning )
- {
- _regionList.Insert( _regionList.Count - 1, region );
- }
- else
- {
- _regionList.Add( region );
- }
- }
- }
- /// <summary>
- /// Add Hot region to the collection.
- /// </summary>
- /// <param name="path">Graphics path</param>
- /// <param name="relativePath">Used relative coordinates for graphics path.</param>
- /// <param name="type">Type of the object which present hot region</param>
- /// <param name="selectedObject">Object which present hot region</param>
- internal void AddHotRegion(
- GraphicsPath path,
- bool relativePath,
- ChartElementType type,
- object selectedObject
- )
- {
- if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
- {
-
- HotRegion region = new HotRegion();
-
- region.SelectedObject = selectedObject;
- region.Type = type;
- region.Path = (GraphicsPath)path.Clone();
- region.BoundingRectangle = path.GetBounds();
- region.RelativeCoordinates = relativePath;
- _regionList.Add( region );
- }
- }
- /// <summary>
- /// This method search for position in Map Areas which is the first
- /// position after Custom areas.
- /// </summary>
- /// <returns>Insert Index</returns>
- internal int FindInsertIndex()
- {
- int insertIndex = 0;
- return insertIndex;
- }
- /// <summary>
- /// Clears this instance.
- /// </summary>
- public void Clear()
- {
- foreach (HotRegion hotRegion in this._regionList)
- hotRegion.Dispose();
-
- this._regionList.Clear();
- }
- #endregion // Methods
- #region IDisposable members
- /// <summary>
- /// Releases unmanaged and - optionally - managed resources
- /// </summary>
- /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (this._regionList != null)
- {
- foreach (HotRegion hotRegion in this._regionList)
- hotRegion.Dispose();
- this._regionList.Clear();
- }
- }
- }
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- #endregion
- }
- /// <summary>
- /// The HitTestResult class contains the result of the hit test function.
- /// </summary>
- public class HitTestResult
- {
- #region Fields
- // Private members
- private object _obj = null;
- private Series _series = null;
- private int _dataPoint = -1;
- private ChartArea _chartArea = null;
- private Axis _axis = null;
- private ChartElementType _type = ChartElementType.Nothing;
- private object _subObject = null;
- #endregion
- #region Properties
- /// <summary>
- /// Gets or sets the data series object.
- /// </summary>
- public Series Series
- {
- get
- {
- return _series;
- }
- set
- {
- _series = value;
- }
- }
- /// <summary>
- /// Gets or sets the data point index.
- /// </summary>
- public int PointIndex
- {
- get
- {
- return _dataPoint;
- }
- set
- {
- _dataPoint = value;
- }
- }
- /// <summary>
- /// Gets or sets the chart area object.
- /// </summary>
- public ChartArea ChartArea
- {
- get
- {
- return _chartArea;
- }
- set
- {
- _chartArea = value;
- }
- }
- /// <summary>
- /// Gets or sets the axis object.
- /// </summary>
- public Axis Axis
- {
- get
- {
- return _axis;
- }
- set
- {
- _axis = value;
- }
- }
- /// <summary>
- /// Gets or sets the chart element type.
- /// </summary>
- public ChartElementType ChartElementType
- {
- get
- {
- return _type;
- }
- set
- {
- _type = value;
- }
- }
- /// <summary>
- /// Gets or sets the selected object.
- /// </summary>
- public object Object
- {
- get
- {
- return _obj;
- }
- set
- {
- _obj = value;
- }
- }
- /// <summary>
- /// Gets or sets the selected sub object.
- /// </summary>
- public object SubObject
- {
- get
- {
- return _subObject;
- }
- set
- {
- _subObject = value;
- }
- }
- #endregion
- }
- /// <summary>
- /// This class represents an array of marker points and
- /// the outline path used for visual object selection in the chart.
- /// </summary>
- /// <remarks>
- /// <see cref="OutlinePath"/> may be null for complex objects or objects with two points or fewer.
- /// </remarks>
- public class ChartElementOutline : IDisposable
- {
- /// <summary>
- /// Initializes a new instance of the <see cref="ChartElementOutline"/> class.
- /// </summary>
- internal ChartElementOutline()
- {
- this.Markers = new ReadOnlyCollection<PointF>( new PointF[] {});
- }
- /// <summary>
- /// Gets the markers.
- /// </summary>
- /// <value>The markers.</value>
- public ReadOnlyCollection<PointF> Markers { get; internal set; }
- /// <summary>
- /// Gets or sets the outline path. The result could be null for complex objects and objects with two points or fewer.
- /// </summary>
- /// <value>The outline path.</value>
- public GraphicsPath OutlinePath { get; internal set; }
- #region IDisposable Members
- /// <summary>
- /// Releases unmanaged and - optionally - managed resources
- /// </summary>
- /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (this.OutlinePath != null)
- {
- this.OutlinePath.Dispose();
- this.OutlinePath = null;
- }
- this.Markers = null;
- }
- }
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
- [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- #endregion
- }
- /// <summary>
- /// This class contains methods used for Windows Forms selection.
- /// </summary>
- internal class Selection : IServiceProvider
- , IDisposable
- {
- #region Fields
- /// <summary>
- /// The chart service container
- /// </summary>
- private IServiceContainer _service = null;
- /// <summary>
- /// Stores the tooltip of the control.
- /// </summary>
- private ToolTip _toolTip = new ToolTip();
- /// <summary>
- /// Used by the tooltip - stores the time when the tooltip is activated.
- /// </summary>
- private DateTime _toolTipActivationTime = DateTime.Now;
- /// <summary>
- /// Stores the last mouse move X and Y coordinates, so we can ignore false calls to
- /// OnMouseMove generated my the tooltip.
- /// </summary>
- private Point _lastMouseMove = new Point(int.MinValue, int.MinValue);
- // ToolTips enabled or disabled from series or legend
- private bool _toolTipsEnabled = false;
- // Tool tips enabled flag checked
- internal bool enabledChecked = false;
- #endregion
- #region Constructors
-
- /// <summary>
- /// Initializes a new instance of the <see cref="Selection"/> class.
- /// </summary>
- /// <param name="service">The service.</param>
- internal Selection(IServiceContainer service)
- {
- this._service = service;
- this._chartControl = this.ChartControl;
-
- // Set up the tooltip
- this._toolTip.Active = true;
- this._toolTip.AutoPopDelay = 30000; // maximum delay possible
- this._toolTip.InitialDelay = 500;
- this._toolTip.ReshowDelay = 50;
- this._toolTip.ShowAlways = true;
- this._toolTip.Active = false;
- }
- /// <summary>
- /// Releases unmanaged and - optionally - managed resources
- /// </summary>
- /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
- private void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (_toolTip != null)
- {
- _toolTip.Dispose();
- _toolTip = null;
- }
- }
- }
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- #endregion //Constructors
- #region Properties
- private Chart _chartControl = null;
- /// <summary>
- /// Returns the attached chart control
- /// </summary>
- internal Chart ChartControl
- {
- get
- {
- if (this._chartControl == null)
- {
- if (this.ChartPicture != null)
- {
- this._chartControl = this.ChartPicture.Chart;
- }
- }
- return this._chartControl;
- }
- }
- private ChartPicture _chartPicture = null;
- /// <summary>
- /// Returns the attached ChartPicture
- /// </summary>
- internal ChartPicture ChartPicture
- {
- get
- {
- if (this._chartPicture == null)
- {
- this._chartPicture = ((IServiceProvider)this).GetService(typeof(ChartImage)) as ChartPicture;
- if (this._chartPicture == null)
- {
- this._chartPicture = ((IServiceProvider)this).GetService(typeof(ChartPicture)) as ChartPicture;
- }
- }
- return this._chartPicture;
- }
- }
- private Data.DataManager _dataManager = null;
- /// <summary>
- /// Gets the chart data manager ( for series access )
- /// </summary>
- internal Data.DataManager DataManager
- {
- get
- {
- if (this._dataManager == null)
- {
- this._dataManager = ((IServiceProvider)this).GetService(typeof(Data.DataManager)) as Data.DataManager;
- }
- return this._dataManager;
- }
- }
- /// <summary>
- /// Gets the chart ChartGraphics
- /// </summary>
- internal ChartGraphics Graph
- {
- get
- {
- if (this.ChartPicture != null)
- {
- return this.ChartPicture.Common.graph;
- }
- return null;
- }
- }
- #endregion //Private Properties
- #region Methods
- #region Tooltips
- /// <summary>
- /// Checks if tooltips are enabled
- /// </summary>
- /// <returns>true if tooltips enabled</returns>
- private bool IsToolTipsEnabled()
- {
- // Enabled checked. Don’t check every time series
- // and data points for tooltips.
- if( enabledChecked )
- {
- return _toolTipsEnabled;
- }
- enabledChecked = true;
- // Annotations loop
- foreach( Annotation annotation in _chartControl.Annotations )
- {
- // ToolTip empty
- if( annotation.ToolTip.Length > 0 )
- {
- // ToolTips enabled
- _toolTipsEnabled = true;
- return true;
- }
- }
- // Data series loop
- foreach( Series series in _chartControl.Series )
- {
- // Check series tooltips
- if( series.ToolTip.Length > 0 ||
- series.LegendToolTip.Length > 0 ||
- series.LabelToolTip.Length > 0)
- {
- // ToolTips enabled
- _toolTipsEnabled = true;
- return true;
- }
- // Check if custom properties (Pie collected slice) that create tooltips are used
- if(series.IsCustomPropertySet(Utilities.CustomPropertyName.CollectedToolTip))
- {
- // ToolTips enabled
- _toolTipsEnabled = true;
- return true;
- }
- // Check point tooltips only for "non-Fast" chart types
- if( !series.IsFastChartType() )
- {
- // Data point loop
- foreach( DataPoint point in series.Points )
- {
- // ToolTip empty
- if( point.ToolTip.Length > 0 ||
- point.LegendToolTip.Length > 0 ||
- point.LabelToolTip.Length > 0)
- {
- // ToolTips enabled
- _toolTipsEnabled = true;
- return true;
- }
- }
- }
- }
- // Legend items loop
- foreach( Legend legend in _chartControl.Legends )
- {
- // Check custom legend items
- foreach( LegendItem legendItem in legend.CustomItems )
- {
- // ToolTip empty
- if( legendItem.ToolTip.Length > 0 )
- {
- _toolTipsEnabled = true;
- return true;
- }
- // Check all custom cells in the legend item
- foreach(LegendCell legendCell in legendItem.Cells)
- {
- if(legendCell.ToolTip.Length > 0)
- {
- _toolTipsEnabled = true;
- return true;
- }
- }
- }
- // Iterate through legend columns
- foreach(LegendCellColumn legendColumn in legend.CellColumns)
- {
- if(legendColumn.ToolTip.Length > 0)
- {
- _toolTipsEnabled = true;
- return true;
- }
- }
- }
- // Title items loop
- foreach( Title title in _chartControl.Titles )
- {
- // ToolTip empty
- if( title.ToolTip.Length > 0 )
- {
- _toolTipsEnabled = true;
- return true;
- }
- }
- // Chart areas loop
- foreach( ChartArea area in _chartControl.ChartAreas )
- {
- // Check if chart area is visible
- if(area.Visible)
- {
- // Axis loop
- foreach(Axis axis in area.Axes)
- {
- // Check ToolTip
- if( axis.ToolTip.Length > 0 )
- {
- _toolTipsEnabled = true;
- return true;
- }
- // Strip lines loop
- foreach(StripLine stripLine in axis.StripLines)
- {
- // Check ToolTip
- if( stripLine.ToolTip.Length > 0 )
- {
- _toolTipsEnabled = true;
- return true;
- }
- }
- // Check custom labels
- foreach(CustomLabel customLabel in axis.CustomLabels)
- {
- if( customLabel.ToolTip.Length > 0 )
- {
- _toolTipsEnabled = true;
- return true;
- }
- }
- }
- }
- }
- // ToolTips disabled
- _toolTipsEnabled = false;
- return false;
- }
- [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily",
- Justification = "Too large of a code change to justify making this change")]
- internal string EvaluateToolTip(System.Windows.Forms.MouseEventArgs e)
- {
- object obj;
- object subObj;
- ChartElementType type;
- int dataPointIndex;
- string seriesName;
- string toolTipText = " ";
- HitTestResult hitTest = this.HitTest(e.X, e.Y, true);
- type = hitTest.ChartElementType;
- dataPointIndex = hitTest.PointIndex;
- seriesName = hitTest.Series != null ? hitTest.Series.Name : String.Empty;
- obj = hitTest.Object;
- subObj = hitTest.SubObject;
- // Get tooltips from data points
- if (type == ChartElementType.DataPoint)
- {
- if (_chartControl.Series.IndexOf(seriesName) >= 0 &&
- dataPointIndex >= 0 &&
- dataPointIndex < _chartControl.Series[seriesName].Points.Count)
- {
- // Take tool tip from data point
- toolTipText = _chartControl.Series[seriesName].Points[dataPointIndex].ReplaceKeywords(_chartControl.Series[seriesName].Points[dataPointIndex].ToolTip);
- }
- else
- {
- DataPoint dataPoint = obj as DataPoint;
- if (dataPoint != null)
- {
- // Take tool tip from data point
- toolTipText = dataPoint.ReplaceKeywords(dataPoint.ToolTip);
- }
- }
- }
- // Get tooltips from data points
- if (type == ChartElementType.DataPointLabel)
- {
- if (_chartControl.Series.IndexOf(seriesName) >= 0 &&
- dataPointIndex >= 0 &&
- dataPointIndex < _chartControl.Series[seriesName].Points.Count)
- {
- // Take tool tip from data point
- toolTipText = _chartControl.Series[seriesName].Points[dataPointIndex].ReplaceKeywords(_chartControl.Series[seriesName].Points[dataPointIndex].LabelToolTip);
- }
- }
- // Get tooltips from custom label
- if (type == ChartElementType.AxisLabels &&
- obj is CustomLabel)
- {
- toolTipText = ((CustomLabel)obj).ToolTip;
- }
- // Get tooltips from data points
- else if (type == ChartElementType.Annotation && obj != null && obj is Annotation)
- {
- // Take tool tip from data point
- toolTipText = ((Annotation)obj).ReplaceKeywords(((Annotation)obj).ToolTip);
- }
- // Get tooltips from axis
- else if (type == ChartElementType.Axis && obj != null && obj is Axis)
- {
- // Take tool tip from strip line
- toolTipText = ((Axis)obj).ToolTip;
- }
- // Get tooltips from strip lines
- else if (type == ChartElementType.StripLines && obj != null && obj is StripLine)
- {
- // Take tool tip from strip line
- toolTipText = ((StripLine)obj).ToolTip;
- }
- // Get tooltips from data points
- else if (type == ChartElementType.Title && obj != null && obj is Title)
- {
- // Take tool tip from data point
- toolTipText = ((Title)obj).ToolTip;
- } // Get tooltips for legend items
- // Get tooltips for legend items
- else if (type == ChartElementType.LegendItem)
- {
- // Take tool tip from legend item
- toolTipText = ((LegendItem)obj).ToolTip;
- // Check if cell has it's own tooltip
- LegendCell legendCell = subObj as LegendCell;
- if (legendCell != null && legendCell.ToolTip.Length > 0)
- {
- toolTipText = legendCell.ToolTip;
- }
- // Check if series is associated with legend item
- if (toolTipText.Length == 0 &&
- seriesName.Length > 0 &&
- _chartControl.Series.IndexOf(seriesName) >= 0)
- {
- // Take tool tip from data point
- if (dataPointIndex == -1)
- {
- if (seriesName.Length > 0)
- {
- // Take tool tip from series
- toolTipText = _chartControl.Series[seriesName].ReplaceKeywords(_chartControl.Series[seriesName].LegendToolTip);
- }
- }
- else
- {
- if (dataPointIndex >= 0 &&
- dataPointIndex < _chartControl.Series[seriesName].Points.Count)
- {
- // Take tool tip from data point
- toolTipText = _chartControl.Series[seriesName].Points[dataPointIndex].ReplaceKeywords(_chartControl.Series[seriesName].Points[dataPointIndex].LegendToolTip);
- }
- }
- }
- }
- // Set event arguments
- ToolTipEventArgs args = new ToolTipEventArgs(e.X, e.Y, toolTipText, hitTest);
- // Event
- _chartControl.OnGetToolTipText(args);
- return args.Text.Trim();
- }
- /// <summary>
- /// Mouse move event handler.
- /// </summary>
- /// <param name="sender">Sender</param>
- /// <param name="e">Arguments</param>
- internal void Selection_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
- {
- // Ignore false calls to OnMouseMove caused by the tootip control.
- if (e.X == this._lastMouseMove.X && e.Y == this._lastMouseMove.Y)
- {
- return;
- }
- else
- {
- this._lastMouseMove.X = e.X;
- this._lastMouseMove.Y = e.Y;
- }
- // Event is not active and tooltip properties are nor set.
- if (!IsToolTipsEnabled() && !_chartControl.IsToolTipEventUsed())
- {
- return;
- }
- string newToolTipText = this.EvaluateToolTip(e);
- if (!String.IsNullOrEmpty(newToolTipText))
- {
- string oldToolTipText = this._toolTip.GetToolTip(this._chartControl);
- TimeSpan timeSpan = DateTime.Now.Subtract(this._toolTipActivationTime);
- if (oldToolTipText != newToolTipText || timeSpan.Milliseconds > 600)
- {
- // Activate the tooltip
- this._toolTip.Active = false;
- this._toolTip.SetToolTip(this._chartControl, newToolTipText);
- this._toolTip.Active = true;
- this._toolTipActivationTime = DateTime.Now;
- }
- }
- else
- {
- // We do not have a tooltip, so deactivate it
- this._toolTip.Active = false;
- this._toolTip.SetToolTip(this._chartControl, string.Empty);
- }
- }
- #endregion //Tooltips
- #region HitTest
- /// <summary>
- /// Call this method to determine the chart element,
- /// if any, that is located at a point defined by the given X and Y
- /// coordinates.
- /// <seealso cref="HitTestResult"/></summary>
- /// <param name="x">The X coordinate for the point in question.
- /// Often obtained from a parameter in an event
- /// (e.g. the X parameter value in the MouseDown event).</param>
- /// <param name="y">The Y coordinate for the point in question.
- /// Often obtained from a parameter in an event
- /// (e.g. the Y parameter value in the MouseDown event).</param>
- /// <param name="requestedElementTypes">
- /// An array of type which specify the types
- /// to test for, on order to filter the result. If omitted checking for
- /// elementTypes will be ignored and all kind of elementTypes will be
- /// valid.
- /// </param>
- /// <param name="ignoreTransparent">Indicates that transparent
- /// elements should be ignored.</param>
- /// <returns>
- /// A array of <see cref="HitTestResult"/> objects,
- /// which provides information concerning the chart element
- /// (if any) that is at the specified location. Result contains at least
- /// one element, which could be ChartElementType.Nothing.
- /// The objects in the result are sorted in from top to bottom of
- /// different layers of control. </returns>
- /// <remarks>Call this method to determine the gauge element
- /// (if any) that is located at a specified point. Often this method is used in
- /// some mouse-related event (e.g. MouseDown)
- /// to determine what gauge element the end-user clicked on.
- /// The X and Y mouse coordinates obtained from the
- /// event parameters are then used for the X and Y parameter
- /// values of this method call. The returned
- /// <see cref="HitTestResult"/> object's properties
- /// can then be used to determine what chart element was clicked on,
- /// and also provides a reference to the actual object selected (if
- /// any).</remarks>
- internal HitTestResult[] HitTest(int x, int y, bool ignoreTransparent, params ChartElementType[] requestedElementTypes)
- {
- List<HitTestResult> result = new List<HitTestResult>();
- ArrayList regionList = this.ChartPicture.Common.HotRegionsList.List;
- if (regionList.Count == 0)
- {
- this.ChartPicture.PaintOffScreen();
- }
- string alowedElements = String.Empty;
- if (requestedElementTypes.Length > 0)
- {
- StringBuilder builder = new StringBuilder();
- foreach (ChartElementType elementType in requestedElementTypes)
- {
- builder.Append(elementType.ToString() + ";");
- }
- alowedElements = builder.ToString();
- }
- float newX;
- float newY;
- float relativeX;
- float relativeY;
- RectangleF newMouseRect;
- // Find mouse position in relative and absolute coordinates
- RectangleF mouseRect = new RectangleF(x - 1, y - 1, 2, 2);
- relativeX = this.Graph.GetRelativePoint(new PointF(x, y)).X;
- relativeY = this.Graph.GetRelativePoint(new PointF(x, y)).Y;
- RectangleF relativeMouseRect = this.Graph.GetRelativeRectangle(mouseRect);
- // Try to pass through series object in design time.
- // The series ussualy contain autogenerated points with short lifetime - during painting;
- // This hit test result will be used in VS2005 desing time click.
- for (int index = regionList.Count - 1; index >= 0; index--)
- {
- HotRegion region = (HotRegion)regionList[index];
- // Check if only looking for specific chart element type
- if (!String.IsNullOrEmpty(alowedElements) && alowedElements.IndexOf(region.Type.ToString() + ";", StringComparison.Ordinal) == -1)
- {
- continue;
- }
- // Change coordinates if relative path is used
- if (region.RelativeCoordinates)
- {
- newX = relativeX;
- newY = relativeY;
- newMouseRect = relativeMouseRect;
- }
- else
- {
- newX = (float)x;
- newY = (float)y;
- newMouseRect = mouseRect;
- }
- // Check if series name and point index are valid
- if (region.SeriesName.Length > 0 &&
- (this.ChartControl.Series.IndexOf(region.SeriesName) < 0 || region.PointIndex >= this.ChartControl.Series[region.SeriesName].Points.Count)
- )
- {
- continue;
- }
- // Check if transparent chart elements should be ignored
- if (ignoreTransparent && IsElementTransparent(region))
- {
- continue;
- }
- // Check intersection with bounding rectangle
- if (region.BoundingRectangle.IntersectsWith(newMouseRect))
- {
- bool pointVisible = false;
- if (region.Path != null)
- {
- // If there is more then one graphical path split them and create
- // image maps for every graphical path separately.
- GraphicsPathIterator iterator = new GraphicsPathIterator(region.Path);
- // There is more then one path.
- if (iterator.SubpathCount > 1)
- {
- GraphicsPath subPath = new GraphicsPath();
- while (iterator.NextMarker(subPath) > 0 && pointVisible == false)
- {
- if (subPath.IsVisible(newX, newY))
- {
- pointVisible = true;
- }
- subPath.Reset();
- }
- }
- // There is only one path
- else if (region.Path.IsVisible(newX, newY))
- {
- pointVisible = true;
- }
- }
- else
- {
- // Point is inside bounding rectangle and path is not specified
- pointVisible = true;
- }
- // Check if point is inside the hot region
- if (pointVisible)
- {
- HitTestResult hitTestToAdd = this.GetHitTestResult(
- region.SeriesName,
- region.PointIndex,
- region.Type,
- region.SelectedObject,
- region.SelectedSubObject
- );
- int elementIndex = result.FindIndex(
- delegate(HitTestResult test)
- {
- if (
- (test.ChartElementType == hitTestToAdd.ChartElementType) &&
- (test.Object == hitTestToAdd.Object) &&
- (test.SubObject == hitTestToAdd.SubObject) &&
- (test.Series == hitTestToAdd.Series) &&
- (test.PointIndex == hitTestToAdd.PointIndex)
- )
- {
- return true;
- }
- return false;
- }
- );
- if (elementIndex == -1)
- {
- result.Add(hitTestToAdd);
- }
- }
- }
- }
- if (result.Count == 0)
- {
- result.Add(this.GetHitTestResult(String.Empty, 0, ChartElementType.Nothing, null, null));
- }
- return result.ToArray();
- }
- /// <summary>
- /// This method performs the hit test and returns a HitTestResult objects.
- /// </summary>
- /// <param name="x">X coordinate</param>
- /// <param name="y">Y coordinate</param>
- /// <returns>Hit test result object</returns>
- [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
- Justification = "X and Y are cartesian coordinates and well understood")]
- internal HitTestResult HitTest(int x, int y)
- {
- return this.HitTest(x, y, false, new ChartElementType[] {})[0];
- }
- /// <summary>
- /// This method performs the hit test and returns a HitTestResult object.
- /// </summary>
- /// <param name="x">X coordinate</param>
- /// <param name="y">Y coordinate</param>
- /// <param name="ignoreTransparent">Indicates that transparent elements should be ignored.</param>
- /// <returns>Hit test result object</returns>
- [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
- Justification = "X and Y are cartesian coordinates and well understood")]
- public HitTestResult HitTest(int x, int y, bool ignoreTransparent)
- {
- return this.HitTest(x, y, ignoreTransparent, new ChartElementType[] { })[0];
- }
- /// <summary>
- /// This method performs the hit test and returns a HitTestResult object.
- /// </summary>
- /// <param name="x">X coordinate</param>
- /// <param name="y">Y coordinate</param>
- /// <param name="requestedElement">Only this chart element will be hit tested.</param>
- /// <returns>Hit test result object</returns>
- [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
- Justification = "X and Y are cartesian coordinates and well understood")]
- public HitTestResult HitTest(int x, int y, ChartElementType requestedElement)
- {
- return this.HitTest(x, y, false, requestedElement)[0];
- }
- /// <summary>
- /// Checks if chart element associated with hot region has transparent background.
- /// </summary>
- /// <param name="region">Element hot region.</param>
- /// <returns>True if chart element is transparent.</returns>
- private bool IsElementTransparent(HotRegion region)
- {
- bool isTransparent = false;
- if (region.Type == ChartElementType.DataPoint)
- {
- if (this.ChartControl != null)
- {
- DataPoint dataPoint = region.SelectedObject as DataPoint;
- if (region.SeriesName.Length > 0)
- {
- dataPoint = this.ChartControl.Series[region.SeriesName].Points[region.PointIndex];
- }
- if (dataPoint != null && dataPoint.Color == Color.Transparent)
- {
- isTransparent = true;
- }
- }
- }
- else if (region.SelectedObject is Axis)
- {
- if (((Axis)region.SelectedObject).LineColor == Color.Transparent)
- {
- isTransparent = true;
- }
- }
- else if (region.SelectedObject is ChartArea)
- {
- if (((ChartArea)region.SelectedObject).BackColor == Color.Transparent)
- {
- isTransparent = true;
- }
- }
- else if (region.SelectedObject is Legend)
- {
- if (((Legend)region.SelectedObject).BackColor == Color.Transparent)
- {
- isTransparent = true;
- }
- }
- else if (region.SelectedObject is Grid)
- {
- if (((Grid)region.SelectedObject).LineColor == Color.Transparent)
- {
- isTransparent = true;
- }
- }
- else if (region.SelectedObject is StripLine)
- {
- if (((StripLine)region.SelectedObject).BackColor == Color.Transparent)
- {
- isTransparent = true;
- }
- }
- else if (region.SelectedObject is TickMark)
- {
- if (((TickMark)region.SelectedObject).LineColor == Color.Transparent)
- {
- isTransparent = true;
- }
- }
- else if (region.SelectedObject is Title)
- {
- Title title = (Title)region.SelectedObject;
- if ((title.Text.Length == 0 || title.ForeColor == Color.Transparent) &&
- (title.BackColor == Color.Transparent || title.BackColor.IsEmpty))
- {
- isTransparent = true;
- }
- }
- return isTransparent;
- }
- /// <summary>
- /// Returns Hit Test Result object
- /// </summary>
- /// <param name="seriesName">Data series Name</param>
- /// <param name="pointIndex">Data point index</param>
- /// <param name="type">Selected Chart element type</param>
- /// <param name="obj">Selected object</param>
- /// <param name="subObject">Selected sub object</param>
- /// <returns>Hit test result object</returns>
- [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily",
- Justification = "Too large of a code change to justify making this change")]
- internal HitTestResult GetHitTestResult(
- string seriesName,
- int pointIndex,
- ChartElementType type,
- object obj,
- object subObject)
- {
- HitTestResult result = new HitTestResult();
- Chart chart = this.ChartControl;
- // If data point is selected convert series
- // name to series object.
- if (seriesName.Length > 0)
- {
- result.Series = chart.Series[seriesName];
- }
- // Selected Object
- result.Object = obj;
- result.SubObject = subObject;
- result.PointIndex = pointIndex;
- result.ChartElementType = type;
- AxisScrollBar scrollBar;
- switch (type)
- {
- case ChartElementType.Axis:
- Axis axis = (Axis)obj;
- result.Axis = axis;
- if (axis != null)
- {
- result.ChartArea = axis.ChartArea;
- }
- break;
- case ChartElementType.DataPoint:
- {
- if (chart.Series.IndexOf(seriesName) >= 0 &&
- pointIndex < chart.Series[seriesName].Points.Count)
- {
- DataPoint dataPoint = chart.Series[seriesName].Points[pointIndex];
- result.Axis = null;
- result.ChartArea = chart.ChartAreas[dataPoint.series.ChartArea];
- result.Object = dataPoint;
- }
- break;
- }
- case ChartElementType.DataPointLabel:
- {
- if (chart.Series.IndexOf(seriesName) >= 0 &&
- pointIndex < chart.Series[seriesName].Points.Count)
- {
- DataPoint dataPoint = chart.Series[seriesName].Points[pointIndex];
- result.Axis = null;
- result.ChartArea = chart.ChartAreas[dataPoint.series.ChartArea];
- result.Object = dataPoint;
- }
- break;
- }
- case ChartElementType.Gridlines:
- Grid gridLines = (Grid)obj;
- result.Axis = gridLines.Axis;
- if (gridLines.Axis != null)
- {
- result.ChartArea = gridLines.Axis.ChartArea;
- }
- break;
- case ChartElementType.LegendArea:
- result.Axis = null;
- result.ChartArea = null;
- break;
- case ChartElementType.LegendItem:
- result.PointIndex = ((LegendItem)obj).SeriesPointIndex;
- result.Axis = null;
- result.ChartArea = null;
- break;
- case ChartElementType.PlottingArea:
- ChartArea area = (ChartArea)obj;
- result.Axis = null;
- result.ChartArea = area;
- break;
- case ChartElementType.StripLines:
- StripLine stripLines = (StripLine)obj;
- result.Axis = stripLines.Axis;
- if (stripLines.Axis != null)
- {
- result.ChartArea = stripLines.Axis.ChartArea;
- }
- break;
- case ChartElementType.TickMarks:
- TickMark tickMarks = (TickMark)obj;
- result.Axis = tickMarks.Axis;
- if (tickMarks.Axis != null)
- {
- result.ChartArea = tickMarks.Axis.ChartArea;
- }
- break;
- case ChartElementType.Title:
- result.Axis = null;
- result.ChartArea = null;
- break;
- case ChartElementType.AxisLabels:
- if (obj is CustomLabel)
- {
- CustomLabel label = (CustomLabel)obj;
- result.Axis = label.Axis;
- result.ChartArea = label.Axis!=null ? label.Axis.ChartArea : null;
- }
- break;
- case ChartElementType.AxisLabelImage:
- if (obj is CustomLabel)
- {
- CustomLabel label = (CustomLabel)obj;
- result.Axis = label.Axis;
- result.ChartArea = label.Axis!=null ? label.Axis.ChartArea : null;
- }
- break;
- case ChartElementType.AxisTitle:
- if (obj is Axis)
- {
- result.Axis = (Axis)obj;
- result.ChartArea = result.Axis.ChartArea;
- }
- break;
- case ChartElementType.ScrollBarLargeDecrement:
- scrollBar = (AxisScrollBar)obj;
- result.Axis = scrollBar.axis;
- if (scrollBar.axis != null)
- {
- result.ChartArea = scrollBar.axis.ChartArea;
- }
- break;
- case ChartElementType.ScrollBarLargeIncrement:
- scrollBar = (AxisScrollBar)obj;
- result.Axis = scrollBar.axis;
- if (scrollBar.axis != null)
- {
- result.ChartArea = scrollBar.axis.ChartArea;
- }
- break;
- case ChartElementType.ScrollBarSmallDecrement:
- scrollBar = (AxisScrollBar)obj;
- result.Axis = scrollBar.axis;
- if (scrollBar.axis != null)
- {
- result.ChartArea = scrollBar.axis.ChartArea;
- }
- break;
- case ChartElementType.ScrollBarSmallIncrement:
- scrollBar = (AxisScrollBar)obj;
- result.Axis = scrollBar.axis;
- if (scrollBar.axis != null)
- {
- result.ChartArea = scrollBar.axis.ChartArea;
- }
- break;
- case ChartElementType.ScrollBarThumbTracker:
- scrollBar = (AxisScrollBar)obj;
- result.Axis = scrollBar.axis;
- if (scrollBar.axis != null)
- {
- result.ChartArea = scrollBar.axis.ChartArea;
- }
- break;
- case ChartElementType.Annotation:
- result.Axis = null;
- result.ChartArea = null;
- break;
- }
- return result;
- }
- #endregion //HitTest
- #region Outline
- /// <summary>
- /// Gets the chart element outline.
- /// </summary>
- /// <param name="chartObject">The chart object.</param>
- /// <param name="elementType">Type of the element.</param>
- /// <returns></returns>
- internal ChartElementOutline GetChartElementOutline(object chartObject, ChartElementType elementType)
- {
- // Check arguments
- if (chartObject == null)
- throw new ArgumentNullException("chartObject");
- // Get outline
- ChartElementOutline result = new ChartElementOutline();
- chartObject = this.GetAutoGeneratedObject(chartObject);
- ArrayList list = this.GetMarkers(chartObject, elementType);
- result.Markers = new ReadOnlyCollection<PointF>((PointF[])list.ToArray(typeof(PointF)));
- result.OutlinePath = GetGraphicsPath(list, chartObject, elementType);
- return result;
- }
- #endregion //Outline
- #region Selection
- /// <summary>
- /// Gets the graphics path.
- /// </summary>
- /// <param name="markers">The markers.</param>
- /// <param name="chartObject">The chart object.</param>
- /// <param name="elementType">Type of the element.</param>
- /// <returns></returns>
- private GraphicsPath GetGraphicsPath(IList markers, object chartObject, ChartElementType elementType)
- {
- bool chartArea3D = false;
- ChartArea chartArea = chartObject as ChartArea;
- if (chartArea != null && elementType == ChartElementType.PlottingArea)
- {
- chartArea3D = IsArea3D(chartArea);
- }
- if (elementType != ChartElementType.DataPoint &&
- elementType != ChartElementType.Gridlines &&
- elementType != ChartElementType.StripLines &&
- elementType != ChartElementType.TickMarks &&
- !chartArea3D
- )
- {
- GraphicsPath path = new GraphicsPath();
- PointF[] points = new PointF[markers.Count];
- markers.CopyTo(points, 0);
- if (points.Length > 3)
- {
- if (elementType == ChartElementType.DataPointLabel)
- {
- for (int i = 0; i < points.Length; i += 4)
- {
- RectangleF rect = RectangleF.FromLTRB(points[i].X, points[i].Y, points[i + 2].X, points[i + 2].Y);
- path.Reset();
- path.AddRectangle(Rectangle.Round(rect));
- }
- }
- else
- {
- if (points.Length == 4)
- {
- Point[] pointsAlligned = new Point[points.Length];
- for (int i = 0; i < points.Length; i++)
- {
- pointsAlligned[i] = Point.Round(points[i]);
- }
- path.AddPolygon(pointsAlligned);
- }
- else
- {
- path.AddPolygon(points);
- }
- }
- }
- return path;
- }
- return null;
- }
- private static Int32 GetDataPointIndex(DataPoint dataPoint)
- {
- int pointIndex = -1;
- if (dataPoint != null && dataPoint.series != null)
- {
- pointIndex = dataPoint.series.Points.IndexOf(dataPoint);
- if (pointIndex == -1 && dataPoint.IsCustomPropertySet("OriginalPointIndex"))
- {
- if (!Int32.TryParse(dataPoint.GetCustomProperty("OriginalPointIndex"), out pointIndex))
- return -1;
- }
- }
- return pointIndex;
- }
- /// <summary>
- /// Gets the auto generated object.
- /// </summary>
- /// <param name="chartObject">The chart object.</param>
- /// <returns></returns>
- private object GetAutoGeneratedObject(object chartObject)
- {
- DataPoint dataPoint = chartObject as DataPoint;
- if (dataPoint != null)
- {
- if (dataPoint.series != null)
- {
- string seriesName = dataPoint.series.Name;
- int pointIndex = dataPoint.series.Points.IndexOf(dataPoint);
- if (this.ChartControl.Series.IndexOf(seriesName) != -1)
- {
- Series series = this.ChartControl.Series[seriesName];
- if (series.Points.Contains(dataPoint))
- {
- return chartObject;
- }
- if (pointIndex >= 0)
- {
- if (series.Points.Count > pointIndex)
- {
- return series.Points[pointIndex];
- }
- }
- }
- }
- }
- Series asSeries = chartObject as Series;
- if (asSeries != null)
- {
- if (this.ChartControl.Series.Contains(asSeries))
- {
- return chartObject;
- }
- if (this.ChartControl.Series.IndexOf(asSeries.Name) != -1)
- {
- return this.ChartControl.Series[asSeries.Name];
- }
- }
- return chartObject;
- }
- /// <summary>
- /// Gets the hot regions.
- /// </summary>
- /// <param name="cntxObj">The CNTX obj.</param>
- /// <param name="elementType">Type of the element.</param>
- /// <returns></returns>
- private HotRegion[] GetHotRegions(object cntxObj, ChartElementType elementType)
- {
- ArrayList result = new ArrayList();
- HotRegionsList hrList = this.ChartPicture.Common.HotRegionsList;
- string dataPointSeries = String.Empty;
- int dataPointIndex = -1;
- for (int i = hrList.List.Count - 1; i >= 0; i--)
- {
- HotRegion rgn = (HotRegion)hrList.List[i];
- if (rgn.Type == elementType)
- {
- switch (rgn.Type)
- {
- case ChartElementType.LegendItem:
- LegendItem legendItem = cntxObj as LegendItem;
- if (legendItem != null)
- {
- if (((LegendItem)rgn.SelectedObject).Name == legendItem.Name)
- {
- result.Add(rgn);
- }
- }
- break;
- case ChartElementType.AxisLabelImage:
- case ChartElementType.AxisLabels:
- CustomLabel label1 = cntxObj as CustomLabel;
- CustomLabel label2 = rgn.SelectedObject as CustomLabel;
- if (label1 != null)
- {
- if (label1 != null && label2 != null)
- {
- if (label1.Axis == label2.Axis)
- {
- if (label1.FromPosition == label2.FromPosition &&
- label1.ToPosition == label2.ToPosition &&
- label1.RowIndex == label2.RowIndex)
- {
- if (rgn.Path == null)
- {
- result.Add(rgn);
- }
- }
- }
- }
- }
- else
- {
- Axis axis = cntxObj as Axis;
- if (axis != null)
- {
- if (axis == label2.Axis)
- {
- if (rgn.Path == null)
- {
- result.Add(rgn);
- }
- }
- }
- }
- break;
- case ChartElementType.DataPointLabel:
- case ChartElementType.DataPoint:
- DataPoint dataPoint = cntxObj as DataPoint;
- if (dataPoint != null)
- {
- if (String.IsNullOrEmpty(dataPointSeries) || dataPointIndex == -1)
- {
- dataPointSeries = dataPoint.series.Name;
- dataPointIndex = GetDataPointIndex(dataPoint);
- }
- if (rgn.PointIndex == dataPointIndex && rgn.SeriesName == dataPointSeries)
- {
- result.Add(rgn);
- }
- }
- else
- {
- DataPointCollection dataPointCollection = cntxObj as DataPointCollection;
- if (dataPointCollection != null)
- {
- cntxObj = dataPointCollection.series;
- }
- Series series = cntxObj as Series;
- if (series != null)
- {
- if (String.IsNullOrEmpty(dataPointSeries) || dataPointIndex == -1)
- {
- dataPointSeries = series.Name;
- }
- if (rgn.SeriesName == dataPointSeries)
- {
- result.Add(rgn);
- }
- }
- }
- break;
- default:
- if (rgn.SelectedObject == cntxObj)
- {
- result.Add(rgn);
- }
- break;
- }
- }
- }
- return (HotRegion[])result.ToArray(typeof(HotRegion));
- }
- /// <summary>
- /// Gets the markers from regions.
- /// </summary>
- /// <param name="chartObject">The chart object.</param>
- /// <param name="elementType">Type of the element.</param>
- /// <returns></returns>
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
- private ArrayList GetMarkersFromRegions(object chartObject, ChartElementType elementType)
- {
- ArrayList list = new ArrayList();
- HotRegion[] regions = this.GetHotRegions(chartObject, elementType);
- ChartGraphics graph = this.Graph;
- RectangleF rect;
- Grid grid = chartObject as Grid;
- if (grid != null)
- {
- foreach (HotRegion rgn in regions)
- {
- if (!IsArea3D(grid.Axis.ChartArea))
- {
- if (IsChartAreaCircular(grid.Axis.ChartArea))
- {
- GraphicsPathIterator iterator = new GraphicsPathIterator(rgn.Path);
- // There is more then one path.
- if (iterator.SubpathCount > 1)
- {
- GraphicsPath subPath = new GraphicsPath();
- while (iterator.NextMarker(subPath) > 0)
- {
- rect = subPath.GetBounds();
- list.Add(new PointF(rect.Left + rect.Width / 2, rect.Top));
- list.Add(new PointF(rect.Right, rect.Top + rect.Height / 2));
- list.Add(new PointF(rect.Right - rect.Width / 2, rect.Bottom));
- list.Add(new PointF(rect.Left, rect.Bottom - rect.Height / 2));
- subPath.Reset();
- }
- }
- }
- else
- {
- // 2D
- rect = this.GetHotRegionRectangle(rgn, RectangleF.Empty, elementType);
- if (grid != null)
- {
- if (grid.GetAxis().AxisPosition == AxisPosition.Bottom ||
- grid.GetAxis().AxisPosition == AxisPosition.Top)
- {
- rect.Offset(rect.Width / 2, 0);
- rect.Width = 0;
- }
- else
- {
- rect.Offset(0, rect.Height / 2);
- rect.Height = 0;
- }
- }
- list.AddRange(this.GetMarkers(rect, false));
- }
- }
- else
- { // 3D
- PointF[] points = rgn.Path.PathPoints;
- for (int i = 0; i < points.Length - 3; i = i + 4)
- { //Each gridline has a corresponding set of 4 points in the path
- //One of the ends of a gridline is in the middle the line between points #0 and #3
- //Another ends of a gridline is in the middle the line between points #1 and #2
- //So we find those middles and put a marks to the ends of the gridline.
- PointF middleP0P3 = new PointF((points[i].X + points[i + 3].X) / 2f, (points[i].Y + points[i + 3].Y) / 2f);
- PointF middleP1P2 = new PointF((points[i + 1].X + points[i + 2].X) / 2f, (points[i + 1].Y + points[i + 2].Y) / 2f);
- list.Add(graph.GetAbsolutePoint(middleP0P3));
- list.Add(graph.GetAbsolutePoint(middleP1P2));
- }
- }
- }
- return list;
- }
- DataPoint dataPoint = chartObject as DataPoint;
- if (dataPoint != null && elementType != ChartElementType.DataPointLabel)
- {
- rect = Rectangle.Empty;
- Series series = dataPoint.series;
- if (this.ChartControl.ChartAreas.IndexOf(series.ChartArea) == -1)
- {
- return list;
- }
- ChartArea area = this.ChartControl.ChartAreas[series.ChartArea];
- PointF pp = this.Transform3D(area, dataPoint);
- if (!(float.IsNaN(pp.X) || float.IsNaN(pp.Y)))
- {
- list.Add(graph.GetAbsolutePoint(pp));
- }
- return list;
- }
- Axis axis = chartObject as Axis;
- if (axis != null && elementType == ChartElementType.AxisTitle)
- {
- foreach (HotRegion rgn in regions)
- {
- if (!IsArea3D(axis.ChartArea))
- { // 2D
- rect = this.GetHotRegionRectangle(rgn, RectangleF.Empty, elementType);
- list.AddRange(this.GetMarkers(rect, elementType));
- }
- else
- { // 3D
- PointF[] points = rgn.Path.PathPoints;
- list.AddRange(points);
- }
- }
- return list;
- }
- LegendItem legendItem = chartObject as LegendItem;
- if (legendItem != null)
- {
- rect = Rectangle.Empty;
- foreach (HotRegion rgn in regions)
- {
- rect = this.GetHotRegionRectangle(rgn, rect, elementType);
- }
- if (!rect.IsEmpty)
- {
- list.AddRange(this.GetMarkers(rect, elementType));
- }
- return list;
- }
- else if (chartObject is Annotation)
- {
- rect = Rectangle.Empty;
- foreach (HotRegion rgn in regions)
- {
- rect = this.GetHotRegionRectangle(rgn, rect, elementType);
- }
- if (!rect.IsEmpty)
- {
- list.AddRange(this.GetMarkers(rect, elementType));
- }
- return list;
- }
- foreach (HotRegion rgn in regions)
- {
- rect = this.GetHotRegionRectangle(rgn, RectangleF.Empty, elementType);
- list.AddRange(this.GetMarkers(rect, elementType));
- }
- return list;
- }
- /// <summary>
- /// Gets the markers.
- /// </summary>
- /// <param name="chartObject">The chart object.</param>
- /// <param name="elementType">Type of the element.</param>
- /// <returns></returns>
- private ArrayList GetMarkers(object chartObject, ChartElementType elementType)
- {
- ChartArea chartArea = chartObject as ChartArea;
- if (chartArea != null)
- {
- return this.GetAreaMarkers(this.Graph, chartArea);
- }
- Axis axis = chartObject as Axis;
- if (axis != null)
- {
- if (
- elementType == ChartElementType.AxisLabelImage ||
- elementType == ChartElementType.AxisLabels ||
- elementType == ChartElementType.AxisTitle
- )
- {
- return this.GetMarkersFromRegions(chartObject, elementType);
- }
- return this.GetAxisMarkers(this.Graph, axis);
- }
- DataPoint dataPoint = chartObject as DataPoint;
- if (dataPoint != null)
- {
- return this.GetMarkersFromRegions(chartObject, elementType);
- }
- Series series = chartObject as Series;
- if (series != null)
- {
- if (elementType == ChartElementType.DataPointLabel)
- {
- return this.GetMarkersFromRegions(chartObject, elementType);
- }
- return this.GetSeriesMarkers(series);
- }
- return this.GetMarkersFromRegions(chartObject, elementType);
- }
- /// <summary>
- /// Determines whether specified chart area is circular or not have axes. These chart areas contain pie, doughnut, polar, radar
- /// </summary>
- /// <param name="area">The area.</param>
- /// <returns>
- /// <c>true</c> if specified chart area is circular; otherwise, <c>false</c>.
- /// </returns>
- private Boolean IsChartAreaCircular(ChartArea area)
- {
- foreach (object o in area.ChartTypes)
- {
- ChartTypes.IChartType chartType = area.Common.ChartTypeRegistry.GetChartType(o.ToString());
- if (chartType != null && (chartType.CircularChartArea || !chartType.RequireAxes))
- {
- return true;
- }
- }
- return false;
- }
- /// <summary>
- /// Determines whether the chart area is in 3D mode.
- /// </summary>
- /// <param name="area">The area.</param>
- /// <returns>
- /// <c>true</c> if the chart area is in 3D mode; otherwise, <c>false</c>.
- /// </returns>
- private Boolean IsArea3D(ChartArea area)
- {
- return area.Area3DStyle.Enable3D && !this.IsChartAreaCircular(area) && area.matrix3D != null && area.matrix3D.IsInitialized();
- }
- /// <summary>
- /// Gets the series markers.
- /// </summary>
- /// <param name="series">The series.</param>
- /// <returns>List of PointF.</returns>
- private ArrayList GetSeriesMarkers(Series series)
- {
- ArrayList list = new ArrayList();
- if (series != null)
- {
- String areaName = series.ChartArea;
- if (String.IsNullOrEmpty(areaName))
- {
- areaName = ChartPicture.ChartAreas.DefaultNameReference;
- }
- if (ChartPicture.ChartAreas.IndexOf(areaName) != -1 && series.Enabled)
- {
- ChartArea chartArea = ChartPicture.ChartAreas[areaName];
- if (ChartControl.Series.IndexOf(series.Name) != -1)
- {
- series = ChartControl.Series[series.Name];
- }
- DataPointCollection points = series.Points;
- // in design mode we have usually fake points
- if (points.Count == 0)
- {
- points = series.fakeDataPoints;
- }
- // transform points in 3D
- foreach (DataPoint point in points)
- {
- PointF pp = this.Transform3D(chartArea, point);
- if (float.IsNaN(pp.X) || float.IsNaN(pp.Y))
- {
- continue;
- }
- list.Add(this.Graph.GetAbsolutePoint(pp));
- }
- }
- }
- return list;
- }
- /// <summary>
- /// Gets the axis markers - list of points where markers are drawn.
- /// </summary>
- /// <param name="graph">The graph.</param>
- /// <param name="axis">The axis.</param>
- /// <returns>List of PointF.</returns>
- private ArrayList GetAxisMarkers(ChartGraphics graph, Axis axis)
- {
- ArrayList list = new ArrayList();
- if (axis == null)
- {
- return list;
- }
- PointF first = PointF.Empty;
- PointF second = PointF.Empty;
- // Set the position of axis
- switch (axis.AxisPosition)
- {
- case AxisPosition.Left:
- first.X = (float)axis.GetAxisPosition();
- first.Y = axis.PlotAreaPosition.Y;
- second.X = (float)axis.GetAxisPosition();
- second.Y = axis.PlotAreaPosition.Bottom;
- first.X -= axis.labelSize + axis.markSize;
- break;
- case AxisPosition.Right:
- first.X = (float)axis.GetAxisPosition();
- first.Y = axis.PlotAreaPosition.Y;
- second.X = (float)axis.GetAxisPosition();
- second.Y = axis.PlotAreaPosition.Bottom;
- second.X += axis.labelSize + axis.markSize;
- break;
- case AxisPosition.Bottom:
- first.X = axis.PlotAreaPosition.X;
- first.Y = (float)axis.GetAxisPosition();
- second.X = axis.PlotAreaPosition.Right;
- second.Y = (float)axis.GetAxisPosition();
- second.Y += axis.labelSize + axis.markSize;
- break;
- case AxisPosition.Top:
- first.X = axis.PlotAreaPosition.X;
- first.Y = (float)axis.GetAxisPosition();
- second.X = axis.PlotAreaPosition.Right;
- second.Y = (float)axis.GetAxisPosition();
- first.Y -= axis.labelSize + axis.markSize;
- break;
- }
- // Update axis line position for circular area
- if (axis.ChartArea.chartAreaIsCurcular)
- {
- second.Y = axis.PlotAreaPosition.Y + axis.PlotAreaPosition.Height / 2f;
- }
- RectangleF rect1 = new RectangleF(first.X, first.Y, second.X - first.X, second.Y - first.Y);
- SizeF size = graph.GetRelativeSize(new SizeF(3, 3));
- if (axis.AxisPosition == AxisPosition.Top || axis.AxisPosition == AxisPosition.Bottom)
- {
- rect1.Inflate(2, size.Height);
- }
- else
- {
- rect1.Inflate(size.Width, 2);
- }
- IList list1 = this.GetMarkers(rect1, ChartElementType.Axis);
- ChartArea area = axis.ChartArea;
- if (this.IsArea3D(area))
- {
- Boolean axisOnEdge = false;
- float zPositon = axis.GetMarksZPosition(out axisOnEdge);
- // Transform coordinates
- Point3D[] points = new Point3D[list1.Count];
- for (int i = 0; i < list1.Count; i++)
- {
- points[i] = new Point3D(((PointF)list1[i]).X, ((PointF)list1[i]).Y, zPositon);
- }
- axis.ChartArea.matrix3D.TransformPoints(points);
- for (int i = 0; i < list1.Count; i++)
- {
- list1[i] = points[i].PointF;
- }
- }
- foreach (PointF p in list1)
- {
- list.Add(graph.GetAbsolutePoint(p));
- }
- return list;
- }
- /// <summary>
- /// Gets the area markers.
- /// </summary>
- /// <param name="graph">The graph.</param>
- /// <param name="area">The area.</param>
- /// <returns>List of PointF.</returns>
- private ArrayList GetAreaMarkers(ChartGraphics graph, ChartArea area)
- {
- ArrayList list = new ArrayList();
- if (area == null)
- {
- return list;
- }
- IList list1 = this.GetMarkers(area.PlotAreaPosition.ToRectangleF(), ChartElementType.PlottingArea);
- if (this.IsChartAreaCircular(area))
- {
- list1 = this.GetMarkers(area.lastAreaPosition, ChartElementType.PlottingArea);
- }
- if (IsArea3D(area))
- {
- float zPositon = 0; // area.areaSceneDepth;
- // Transform coordinates
- Point3D[] points = new Point3D[list1.Count];
- for (int i = 0; i < list1.Count; i++)
- {
- points[i] = new Point3D(((PointF)list1[i]).X, ((PointF)list1[i]).Y, zPositon);
- }
- area.matrix3D.TransformPoints(points);
- for (int i = 0; i < list1.Count; i++)
- {
- list1[i] = points[i].PointF;
- }
- }
- foreach (PointF p in list1)
- {
- list.Add(graph.GetAbsolutePoint(p));
- }
- return list;
- }
- /// <summary>
- /// Builds list of markers (PointF) based on rectangle
- /// </summary>
- /// <param name="rect">The rectangle</param>
- /// <param name="elementType">The type of chart elements to retrieve.</param>
- /// <returns>List of PointF</returns>
- private ArrayList GetMarkers(RectangleF rect, ChartElementType elementType)
- {
- if (elementType.ToString().StartsWith("Legend", StringComparison.Ordinal) || elementType.ToString().StartsWith("Title", StringComparison.Ordinal))
- {
- rect.Inflate(4f, 4f);
- }
- if (elementType.ToString().StartsWith("PlottingArea", StringComparison.Ordinal))
- {
- SizeF relSize = this.Graph.GetRelativeSize(new SizeF(4f, 4f));
- rect.Inflate(relSize.Width, relSize.Height);
- }
- if ((elementType != ChartElementType.Nothing) && (elementType != ChartElementType.PlottingArea))
- {
- return this.GetMarkers(rect, false);
- }
- return this.GetMarkers(rect, true);
- }
- /// <summary>
- /// Builds list of markers (PointF) based on rectangle
- /// </summary>
- /// <param name="rect">The rectangle</param>
- /// <param name="addAdditionalMarkers">Add additional markers to the rectangle.</param>
- /// <returns>List of PointF</returns>
- private ArrayList GetMarkers(RectangleF rect, Boolean addAdditionalMarkers)
- {
- ArrayList list = new ArrayList();
- if (!addAdditionalMarkers)
- {
- if (rect.Width > 0 && rect.Height > 0)
- {
- list.Add(new PointF(rect.Left, rect.Top));
- list.Add(new PointF(rect.Right, rect.Top));
- list.Add(new PointF(rect.Right, rect.Bottom));
- list.Add(new PointF(rect.Left, rect.Bottom));
- }
- else if (rect.Width > 0)
- {
- list.Add(new PointF(rect.Left, rect.Top));
- list.Add(new PointF(rect.Right, rect.Top));
- }
- else if (rect.Height > 0)
- {
- list.Add(new PointF(rect.Left, rect.Top));
- list.Add(new PointF(rect.Left, rect.Bottom));
- }
- }
- else
- {
- if (rect.Width > 0)
- {
- list.Add(new PointF(rect.Left, rect.Top));
- if (rect.Width > 30)
- {
- list.Add(new PointF(rect.Left + rect.Width / 2, rect.Top));
- }
- list.Add(new PointF(rect.Right, rect.Top));
- if (rect.Height > 30)
- {
- list.Add(new PointF(rect.Right, rect.Top + rect.Height / 2));
- }
- list.Add(new PointF(rect.Right, rect.Bottom));
- if (rect.Width > 30)
- {
- list.Add(new PointF(rect.Left + rect.Width / 2, rect.Bottom));
- }
- list.Add(new PointF(rect.Left, rect.Bottom));
- if (rect.Height > 30)
- {
- list.Add(new PointF(rect.Left, rect.Top + rect.Height / 2));
- }
- }
- else if (rect.Width > 0)
- {
- list.Add(new PointF(rect.Left, rect.Top));
- if (rect.Width > 30)
- {
- list.Add(new PointF(rect.Left + rect.Width / 2, rect.Top));
- }
- list.Add(new PointF(rect.Right, rect.Top));
- }
- else if (rect.Height > 0)
- {
- list.Add(new PointF(rect.Left, rect.Bottom));
- if (rect.Height > 30)
- {
- list.Add(new PointF(rect.Left, rect.Top + rect.Height / 2));
- }
- list.Add(new PointF(rect.Left, rect.Top));
- }
- }
- return list;
- }
- /// <summary>
- /// Gets the region markers from graphics path.
- /// </summary>
- /// <param name="path">The path.</param>
- /// <returns>List of PointF.</returns>
- private ArrayList GetRegionMarkers(GraphicsPath path)
- {
- return new ArrayList(path.PathPoints);
- }
- /// <summary>
- /// Calculates a DataPoint of 3D area into PointF to draw.
- /// </summary>
- /// <param name="chartArea">3D chart area</param>
- /// <param name="point">The DataPoint</param>
- /// <returns>Calculated PointF</returns>
- private PointF Transform3D(ChartArea chartArea, DataPoint point)
- {
- if (chartArea is ChartArea && IsArea3D(chartArea))
- {
- // Get anotation Z coordinate (use scene depth or anchored point Z position)
- float positionZ = chartArea.areaSceneDepth;
- if (point != null && point.series != null)
- {
- float depth = 0f;
- chartArea.GetSeriesZPositionAndDepth(
- point.series,
- out depth,
- out positionZ);
- positionZ += depth / 2f;
- }
- PointF pf = point.positionRel;
- // Define 3D points of annotation object
- Point3D[] annot3DPoints = new Point3D[1];
- annot3DPoints[0] = new Point3D(pf.X, pf.Y, positionZ);
- // Tranform cube coordinates
- chartArea.matrix3D.TransformPoints(annot3DPoints);
- return annot3DPoints[0].PointF;
- }
- return point.positionRel;
- }
- /// <summary>
- /// Gets the hot region rectangle.
- /// </summary>
- /// <param name="rgn">The hot region.</param>
- /// <param name="unionWith">The rectangle to union with.</param>
- /// <param name="elementType">The type of the element.</param>
- /// <returns>Returns the rectangle around the hot region.</returns>
- private RectangleF GetHotRegionRectangle(HotRegion rgn, RectangleF unionWith, ChartElementType elementType)
- {
- RectangleF rect;
- if (rgn.Path != null)
- {
- rect = rgn.Path.GetBounds();
- }
- else
- {
- rect = rgn.BoundingRectangle;
- }
- if (rgn.RelativeCoordinates)
- {
- rect = this.Graph.GetAbsoluteRectangle(rect);
- }
- if (elementType == ChartElementType.AxisLabels)
- {
- if (rect.Width > rect.Height)
- {
- rect.Inflate(-5, -2);
- }
- else if (rect.Width < rect.Height)
- {
- rect.Inflate(-2, -5);
- }
- }
- if (!unionWith.IsEmpty)
- {
- return RectangleF.Union(unionWith, rect);
- }
- return rect;
- }
- #endregion //Selection
- #endregion //Tooltips
- #region IServiceProvider Members
- /// <summary>
- /// Gets the service object of the specified type.
- /// </summary>
- /// <param name="serviceType">An object that specifies the type of service object to get.</param>
- /// <returns>
- /// A service object of type <paramref name="serviceType"/>. It returns null
- /// if there is no service object of type <paramref name="serviceType"/>.
- /// </returns>
- object IServiceProvider.GetService(Type serviceType)
- {
- if (serviceType == typeof(Selection))
- {
- return this;
- }
- if (_service != null)
- {
- return _service.GetService(serviceType);
- }
- return null;
- }
- #endregion
- }
- /// <summary>
- /// The ToolTipEventArgs class stores the tool tips event arguments.
- /// </summary>
- public class ToolTipEventArgs : EventArgs
- {
- #region Private fields
- // Private fields for properties values storage
- private int x = 0;
- private int y = 0;
- private string text = "";
- private HitTestResult result = new HitTestResult();
-
- #endregion
- #region Constructors
-
- /// <summary>
- /// ToolTipEventArgs constructor. Creates ToolTip event arguments.
- /// </summary>
- /// <param name="x">X-coordinate of mouse.</param>
- /// <param name="y">Y-coordinate of mouse.</param>
- /// <param name="text">Tooltip text.</param>
- /// <param name="result">Hit test result object.</param>
- [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
- Justification = "X and Y are cartesian coordinates and well understood")]
- public ToolTipEventArgs(int x, int y, string text, HitTestResult result)
- {
- this.x = x;
- this.y = y;
- this.text = text;
- this.result = result;
- }
- #endregion
- #region Properties
- /// <summary>
- /// Gets the x-coordinate of the mouse.
- /// </summary>
- [
- SRDescription("DescriptionAttributeToolTipEventArgs_X"),
- ]
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "X")]
- public int X
- {
- get
- {
- return x;
- }
- }
- /// <summary>
- /// Gets the result of the hit test.
- /// </summary>
- [
- SRDescription("DescriptionAttributeToolTipEventArgs_HitTestResult"),
- ]
- public HitTestResult HitTestResult
- {
- get
- {
- return result;
- }
- }
- /// <summary>
- /// Gets the y-coordinate of the mouse.
- /// </summary>
- [
- SRDescription("DescriptionAttributeToolTipEventArgs_Y"),
- ]
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Y")]
- public int Y
- {
- get
- {
- return y;
- }
- }
- /// <summary>
- /// Gets the text of the tooltip.
- /// </summary>
- [
- SRDescription("DescriptionAttributeToolTipEventArgs_Text"),
- ]
- public string Text
- {
- get
- {
- return text;
- }
- set
- {
- text = value;
- }
- }
- #endregion
- }
- }
|