AnnotationBase.cs 160 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. //
  5. // Purpose: Base class for all anotation objects. Provides
  6. // basic set of properties and methods.
  7. //
  8. using System;
  9. using System.Windows.Forms;
  10. using System.Collections;
  11. using System.ComponentModel;
  12. using System.Diagnostics;
  13. using System.Diagnostics.CodeAnalysis;
  14. using System.Drawing;
  15. using System.Drawing.Design;
  16. using System.Drawing.Drawing2D;
  17. using System.Globalization;
  18. using FastReport.DataVisualization.Charting.Utilities;
  19. namespace FastReport.DataVisualization.Charting
  20. {
  21. #region Enumerations
  22. /// <summary>
  23. /// Annotation object selection points style.
  24. /// </summary>
  25. /// <remarks>
  26. /// Enumeration is for internal use only and should not be part of the documentation.
  27. /// </remarks>
  28. internal enum SelectionPointsStyle
  29. {
  30. /// <summary>
  31. /// Selection points are displayed top left and bottom right corners
  32. /// </summary>
  33. TwoPoints,
  34. /// <summary>
  35. /// Selection points are displayed on all sides and corners of the rectangle.
  36. /// </summary>
  37. Rectangle,
  38. }
  39. /// <summary>
  40. /// Annotation object resizing\moving mode.
  41. /// </summary>
  42. /// <remarks>
  43. /// Enumeration is for internal use only and should not be part of the documentation.
  44. /// </remarks>
  45. internal enum ResizingMode
  46. {
  47. /// <summary>
  48. /// Top Left selection handle is used.
  49. /// </summary>
  50. TopLeftHandle = 0,
  51. /// <summary>
  52. /// Top selection handle is used.
  53. /// </summary>
  54. TopHandle = 1,
  55. /// <summary>
  56. /// Top Right selection handle is used.
  57. /// </summary>
  58. TopRightHandle = 2,
  59. /// <summary>
  60. /// Right selection handle is used.
  61. /// </summary>
  62. RightHandle = 3,
  63. /// <summary>
  64. /// Bottom Right selection handle is used.
  65. /// </summary>
  66. BottomRightHandle = 4,
  67. /// <summary>
  68. /// Bottom selection handle is used.
  69. /// </summary>
  70. BottomHandle = 5,
  71. /// <summary>
  72. /// Bottom Left selection handle is used.
  73. /// </summary>
  74. BottomLeftHandle = 6,
  75. /// <summary>
  76. /// Left selection handle is used.
  77. /// </summary>
  78. LeftHandle = 7,
  79. /// <summary>
  80. /// Anchor selection handle is used.
  81. /// </summary>
  82. AnchorHandle = 8,
  83. /// <summary>
  84. /// No selection handles used - moving mode.
  85. /// </summary>
  86. Moving = 16,
  87. /// <summary>
  88. /// Moving points of the annotation path.
  89. /// </summary>
  90. MovingPathPoints = 32,
  91. /// <summary>
  92. /// No moving or resizing.
  93. /// </summary>
  94. None = 64,
  95. }
  96. #endregion
  97. /// <summary>
  98. /// <b>Annotation</b> is an abstract class that defines properties and methods
  99. /// common to all annotations.
  100. /// </summary>
  101. /// <remarks>
  102. /// All annotations are derived from the <b>Annotation</b> class, which can be
  103. /// used to set properties common to all annotation objects (e.g. color, position,
  104. /// anchoring and others).
  105. /// </remarks>
  106. [
  107. SRDescription("DescriptionAttributeAnnotation_Annotation"),
  108. DefaultProperty("Name"),
  109. ]
  110. public abstract class Annotation : ChartNamedElement
  111. {
  112. #region Fields
  113. // Name of the chart area the annotation is clipped to
  114. private string _clipToChartArea = Constants.NotSetValue;
  115. // Indicates that annotation is selected
  116. private bool _isSelected = false;
  117. // Indicates that annotation size is defined in relative chart coordinates
  118. private bool _isSizeAlwaysRelative = true;
  119. // Position attribute fields
  120. private double _x = double.NaN;
  121. private double _y = double.NaN;
  122. private double _width = double.NaN;
  123. private double _height = double.NaN;
  124. // Annotation axes attaching fields
  125. private string _axisXName = String.Empty;
  126. private string _axisYName = String.Empty;
  127. private Axis _axisX = null;
  128. private Axis _axisY = null;
  129. // Visual attribute fields
  130. private bool _visible = true;
  131. private ContentAlignment _alignment = ContentAlignment.MiddleCenter;
  132. private Color _foreColor = Color.Black;
  133. private FontCache _fontCache = new FontCache();
  134. private Font _textFont;
  135. private TextStyle _textStyle = TextStyle.Default;
  136. internal Color lineColor = Color.Black;
  137. private int _lineWidth = 1;
  138. private ChartDashStyle _lineDashStyle = ChartDashStyle.Solid;
  139. private Color _backColor = Color.Empty;
  140. private ChartHatchStyle _backHatchStyle = ChartHatchStyle.None;
  141. private GradientStyle _backGradientStyle = GradientStyle.None;
  142. private Color _backSecondaryColor = Color.Empty;
  143. private Color _shadowColor = Color.FromArgb(128, 0, 0, 0);
  144. private int _shadowOffset = 0;
  145. // Anchor position attribute fields
  146. private string _anchorDataPointName = String.Empty;
  147. private DataPoint _anchorDataPoint = null;
  148. private DataPoint _anchorDataPoint2 = null;
  149. private double _anchorX = double.NaN;
  150. private double _anchorY = double.NaN;
  151. internal double anchorOffsetX = 0.0;
  152. internal double anchorOffsetY = 0.0;
  153. internal ContentAlignment anchorAlignment = ContentAlignment.BottomCenter;
  154. // Selection handles position (starting top-left and moving clockwise)
  155. internal RectangleF[] selectionRects = null;
  156. // Annotation tooltip
  157. private string _tooltip = String.Empty;
  158. // Selection handles size
  159. internal const int selectionMarkerSize = 6;
  160. // Pre calculated relative position of annotation and anchor point
  161. internal RectangleF currentPositionRel = new RectangleF(float.NaN, float.NaN, float.NaN, float.NaN);
  162. internal PointF currentAnchorLocationRel = new PointF(float.NaN, float.NaN);
  163. // Smart labels style
  164. private AnnotationSmartLabelStyle _smartLabelStyle = null;
  165. // Index of last selected point in the annotation path
  166. internal int currentPathPointIndex = -1;
  167. // Group this annotation belongs too
  168. internal AnnotationGroup annotationGroup = null;
  169. // Selection and editing permissions
  170. private bool _allowSelecting = false;
  171. private bool _allowMoving = false;
  172. private bool _allowAnchorMoving = false;
  173. private bool _allowResizing = false;
  174. private bool _allowTextEditing = false;
  175. private bool _allowPathEditing = false;
  176. // Indicates that annotation position was changed. Flag used to fire events.
  177. internal bool positionChanged = false;
  178. // Relative location of last placement position
  179. internal PointF lastPlacementPosition = PointF.Empty;
  180. // Relative location of annotation anchor, when it's started to move
  181. internal PointF startMoveAnchorLocationRel = PointF.Empty;
  182. // Relative position of annotation, when it's started to move/resize
  183. internal RectangleF startMovePositionRel = RectangleF.Empty;
  184. // Relative position of annotation, when it's started to move/resize
  185. internal GraphicsPath startMovePathRel = null;
  186. /// <summary>
  187. /// Limit of annotation width and height.
  188. /// </summary>
  189. internal static double WidthHightLimit = 290000000;
  190. #endregion
  191. #region Constructors
  192. /// <summary>
  193. /// Initializes a new instance of the <see cref="Annotation"/> class.
  194. /// </summary>
  195. protected Annotation()
  196. {
  197. _textFont = _fontCache.DefaultFont;
  198. }
  199. #endregion
  200. #region Properties
  201. #region Miscellaneous
  202. /// <summary>
  203. /// Gets or sets an annotation's unique name.
  204. /// </summary>
  205. /// <value>
  206. /// A <b>string</b> that represents an annotation's unique name.
  207. /// </value>
  208. [
  209. SRCategory("CategoryAttributeMisc"),
  210. Bindable(true),
  211. SRDescription("DescriptionAttributeName4"),
  212. ParenthesizePropertyNameAttribute(true),
  213. ]
  214. public override string Name
  215. {
  216. get
  217. {
  218. return base.Name;
  219. }
  220. set
  221. {
  222. base.Name = value;
  223. CallOnModifing();
  224. }
  225. }
  226. /// <summary>
  227. /// Gets or sets an annotation's type name.
  228. /// </summary>
  229. /// <remarks>
  230. /// This property is used to get the name of each annotation Style
  231. /// (e.g. Line, Rectangle, Ellipse).
  232. /// <para>
  233. /// This property is for internal use and is hidden at design and run time.
  234. /// </para>
  235. /// </remarks>
  236. [
  237. SRCategory("CategoryAttributeMisc"),
  238. Bindable(true),
  239. Browsable(false),
  240. EditorBrowsableAttribute(EditorBrowsableState.Never),
  241. DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
  242. SerializationVisibilityAttribute(SerializationVisibility.Hidden),
  243. SRDescription("DescriptionAttributeAnnotation_AnnotationType"),
  244. ]
  245. public abstract string AnnotationType
  246. {
  247. get;
  248. }
  249. /// <summary>
  250. /// Gets or sets the name of the chart area which an annotation is clipped to.
  251. /// </summary>
  252. /// <value>
  253. /// A string which represents the name of an existing chart area.
  254. /// </value>
  255. /// <remarks>
  256. /// If the chart area name is specified, an annotation will only be drawn inside the
  257. /// plotting area of the chart area specified. All parts of the annotation
  258. /// outside of the plotting area will be clipped.
  259. /// <para>
  260. /// To disable chart area clipping, set the property to "NotSet" or an empty string.
  261. /// </para>
  262. /// </remarks>
  263. [
  264. SRCategory("CategoryAttributeMisc"),
  265. DefaultValue(Constants.NotSetValue),
  266. SRDescription("DescriptionAttributeAnnotationClipToChartArea"),
  267. TypeConverter(typeof(LegendAreaNameConverter))
  268. ]
  269. virtual public string ClipToChartArea
  270. {
  271. get
  272. {
  273. return _clipToChartArea;
  274. }
  275. set
  276. {
  277. if (value != _clipToChartArea)
  278. {
  279. if (String.IsNullOrEmpty(value))
  280. {
  281. _clipToChartArea = Constants.NotSetValue;
  282. }
  283. else
  284. {
  285. if (Chart != null && Chart.ChartAreas != null)
  286. {
  287. Chart.ChartAreas.VerifyNameReference(value);
  288. }
  289. _clipToChartArea = value;
  290. }
  291. this.Invalidate();
  292. CallOnModifing();
  293. }
  294. }
  295. }
  296. /// <summary>
  297. /// Gets or sets the smart labels style of an annotation.
  298. /// </summary>
  299. /// <value>
  300. /// An <see cref="AnnotationSmartLabelStyle"/> object that represents an annotation's
  301. /// smart labels style properties.
  302. /// </value>
  303. /// <remarks>
  304. /// Smart labels are used to prevent an annotation from overlapping data point labels
  305. /// and other annotations.
  306. /// <para>
  307. /// Note that data point labels must also have smart labels enabled.
  308. /// </para>
  309. /// </remarks>
  310. [
  311. Browsable(true),
  312. SRCategory("CategoryAttributeMisc"),
  313. Bindable(true),
  314. SRDescription("DescriptionAttributeSmartLabels"),
  315. DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
  316. ]
  317. public AnnotationSmartLabelStyle SmartLabelStyle
  318. {
  319. get
  320. {
  321. if (this._smartLabelStyle == null)
  322. {
  323. this._smartLabelStyle = new AnnotationSmartLabelStyle(this);
  324. }
  325. return _smartLabelStyle;
  326. }
  327. set
  328. {
  329. value.chartElement = this;
  330. _smartLabelStyle = value;
  331. this.Invalidate();
  332. CallOnModifing();
  333. }
  334. }
  335. /// <summary>
  336. /// Gets the group, if any, the annotation belongs to.
  337. /// </summary>
  338. [
  339. Browsable(false),
  340. DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
  341. SerializationVisibilityAttribute(SerializationVisibility.Hidden),
  342. ]
  343. public AnnotationGroup AnnotationGroup
  344. {
  345. get { return this.annotationGroup; }
  346. }
  347. #endregion
  348. #region Position
  349. /// <summary>
  350. /// Gets or sets a flag that specifies whether the size of an annotation is always
  351. /// defined in relative chart coordinates.
  352. /// <seealso cref="Width"/>
  353. /// <seealso cref="Height"/>
  354. /// </summary>
  355. /// <value>
  356. /// <b>True</b> if an annotation's <see cref="Width"/> and <see cref="Height"/> are always
  357. /// in chart relative coordinates, <b>false</b> otherwise.
  358. /// </value>
  359. /// <remarks>
  360. /// An annotation's width and height may be set in relative chart or axes coordinates.
  361. /// By default, relative chart coordinates are used.
  362. /// <para>
  363. /// To use axes coordinates for size set the <b>IsSizeAlwaysRelative</b> property to
  364. /// <b>false</b> and either anchor the annotation to a data point or set the
  365. /// <see cref="AxisX"/> or <see cref="AxisY"/> properties.
  366. /// </para>
  367. /// </remarks>
  368. [
  369. SRCategory("CategoryAttributePosition"),
  370. DefaultValue(true),
  371. SRDescription("DescriptionAttributeSizeAlwaysRelative"),
  372. ]
  373. virtual public bool IsSizeAlwaysRelative
  374. {
  375. get
  376. {
  377. return _isSizeAlwaysRelative;
  378. }
  379. set
  380. {
  381. _isSizeAlwaysRelative = value;
  382. this.ResetCurrentRelativePosition();
  383. Invalidate();
  384. CallOnModifing();
  385. }
  386. }
  387. /// <summary>
  388. /// Gets or sets the X coordinate of an annotation.
  389. /// <seealso cref="AnchorDataPoint"/>
  390. /// <seealso cref="AnchorX"/>
  391. /// </summary>
  392. /// <value>
  393. /// A Double value that represents the X coordinate of an annotation.
  394. /// </value>
  395. /// <remarks>
  396. /// The X coordinate of an annotation is in relative chart coordinates or axes coordinates. Chart
  397. /// relative coordinates are used by default.
  398. /// <para>
  399. /// To use axes coordinates, anchor
  400. /// an annotation to a data point using the <see cref="AnchorDataPoint"/> property, or
  401. /// set the annotation axes using the <see cref="AxisX"/> or <see cref="AxisY"/> properties.
  402. /// </para>
  403. /// <para>
  404. /// Set the X position to Double.NaN ("NotSet") to achieve automatic position calculation
  405. /// when the annotation is anchored using the <see cref="AnchorDataPoint"/> property or
  406. /// the <see cref="AnchorX"/> and <see cref="AnchorY"/> properties.
  407. /// </para>
  408. /// </remarks>
  409. [
  410. SRCategory("CategoryAttributePosition"),
  411. DefaultValue(double.NaN),
  412. SRDescription("DescriptionAttributeAnnotationBaseX"),
  413. RefreshPropertiesAttribute(RefreshProperties.All),
  414. TypeConverter(typeof(DoubleNanValueConverter)),
  415. ]
  416. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "X")]
  417. virtual public double X
  418. {
  419. get
  420. {
  421. return _x;
  422. }
  423. set
  424. {
  425. _x = value;
  426. this.ResetCurrentRelativePosition();
  427. Invalidate();
  428. CallOnModifing();
  429. }
  430. }
  431. /// <summary>
  432. /// Gets or sets the Y coordinate of an annotation.
  433. /// <seealso cref="AnchorDataPoint"/>
  434. /// <seealso cref="AnchorY"/>
  435. /// </summary>
  436. /// <value>
  437. /// A Double value that represents the Y coordinate of an annotation.
  438. /// </value>
  439. /// <remarks>
  440. /// The Y coordinate of an annotation is in relative chart coordinates or axes coordinates. Chart
  441. /// relative coordinates are used by default.
  442. /// <para>
  443. /// To use axes coordinates, anchor
  444. /// an annotation to a data point using the <see cref="AnchorDataPoint"/> property, or
  445. /// set the annotation axes using the <see cref="AxisX"/> or <see cref="AxisY"/> properties.
  446. /// </para>
  447. /// <para>
  448. /// Set the Y position to Double.NaN ("NotSet") to achieve automatic position calculation
  449. /// when the annotation is anchored using the <see cref="AnchorDataPoint"/> property or
  450. /// the <see cref="AnchorX"/> and <see cref="AnchorY"/> properties.
  451. /// </para>
  452. /// </remarks>
  453. [
  454. SRCategory("CategoryAttributePosition"),
  455. DefaultValue(double.NaN),
  456. SRDescription("DescriptionAttributeAnnotationBaseY"),
  457. RefreshPropertiesAttribute(RefreshProperties.All),
  458. TypeConverter(typeof(DoubleNanValueConverter)),
  459. ]
  460. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Y")]
  461. virtual public double Y
  462. {
  463. get
  464. {
  465. return _y;
  466. }
  467. set
  468. {
  469. _y = value;
  470. this.ResetCurrentRelativePosition();
  471. Invalidate();
  472. CallOnModifing();
  473. }
  474. }
  475. /// <summary>
  476. /// Gets or sets an annotation's width.
  477. /// <seealso cref="IsSizeAlwaysRelative"/>
  478. /// <seealso cref="AxisX"/>
  479. /// </summary>
  480. /// <value>
  481. /// A Double value that represents an annotation's width.
  482. /// </value>
  483. /// <remarks>
  484. /// An annotation's width can be a negative value, in which case the annotation orientation
  485. /// is switched.
  486. /// <para>
  487. /// Annotation width can be in relative chart or axes coordinates. Chart
  488. /// relative coordinates are used by default.
  489. /// </para>
  490. /// <para>
  491. /// To use axes coordinates, anchor
  492. /// an annotation to a data point using the <see cref="AnchorDataPoint"/> property, or
  493. /// set the annotation axes using the <see cref="AxisX"/> or <see cref="AxisY"/> properties
  494. /// and set the <see cref="IsSizeAlwaysRelative"/> property to <b>false</b>.
  495. /// </para>
  496. /// <para>
  497. /// Set the width to Double.NaN ("NotSet") to achieve automatic size calculation for
  498. /// annotations with text. The size will automatically be calculated based on
  499. /// the annotation text and font size.
  500. /// </para>
  501. /// </remarks>
  502. [
  503. SRCategory("CategoryAttributePosition"),
  504. DefaultValue(double.NaN),
  505. SRDescription("DescriptionAttributeAnnotationWidth"),
  506. RefreshPropertiesAttribute(RefreshProperties.All),
  507. TypeConverter(typeof(DoubleNanValueConverter)),
  508. ]
  509. virtual public double Width
  510. {
  511. get
  512. {
  513. return _width;
  514. }
  515. set
  516. {
  517. if (value < -WidthHightLimit || value > WidthHightLimit)
  518. {
  519. throw new ArgumentException(SR.ExceptionValueMustBeInRange("Width", (-WidthHightLimit).ToString(CultureInfo.CurrentCulture), WidthHightLimit.ToString(CultureInfo.CurrentCulture)));
  520. }
  521. _width = value;
  522. this.ResetCurrentRelativePosition();
  523. Invalidate();
  524. CallOnModifing();
  525. }
  526. }
  527. /// <summary>
  528. /// Gets or sets an annotation's height.
  529. /// <seealso cref="IsSizeAlwaysRelative"/>
  530. /// <seealso cref="AxisY"/>
  531. /// </summary>
  532. /// <value>
  533. /// A Double value that represents an annotation's height.
  534. /// </value>
  535. /// <remarks>
  536. /// An annotation's height can be a negative value, in which case the annotation orientation
  537. /// is switched.
  538. /// <para>
  539. /// Annotation height can be in relative chart or axes coordinates. Chart
  540. /// relative coordinates are used by default.
  541. /// </para>
  542. /// <para>
  543. /// To use axes coordinates, anchor
  544. /// an annotation to a data point using the <see cref="AnchorDataPoint"/> property, or
  545. /// set the annotation axes using the <see cref="AxisX"/> or <see cref="AxisY"/> properties
  546. /// and set the <see cref="IsSizeAlwaysRelative"/> property to <b>false</b>.
  547. /// </para>
  548. /// <para>
  549. /// Set the height to Double.NaN ("NotSet") to achieve automatic size calculation for
  550. /// annotations with text. The size will automatically be calculated based on
  551. /// the annotation text and font size.
  552. /// </para>
  553. /// </remarks>
  554. [
  555. SRCategory("CategoryAttributePosition"),
  556. DefaultValue(double.NaN),
  557. SRDescription("DescriptionAttributeAnnotationHeight"),
  558. RefreshPropertiesAttribute(RefreshProperties.All),
  559. TypeConverter(typeof(DoubleNanValueConverter)),
  560. ]
  561. virtual public double Height
  562. {
  563. get
  564. {
  565. return _height;
  566. }
  567. set
  568. {
  569. if (value < -WidthHightLimit || value > WidthHightLimit)
  570. {
  571. throw new ArgumentException(SR.ExceptionValueMustBeInRange("Height", (-WidthHightLimit).ToString(CultureInfo.CurrentCulture), WidthHightLimit.ToString(CultureInfo.CurrentCulture)));
  572. }
  573. _height = value;
  574. this.ResetCurrentRelativePosition();
  575. Invalidate();
  576. CallOnModifing();
  577. }
  578. }
  579. /// <summary>
  580. /// Gets or sets an annotation position's right boundary.
  581. /// <seealso cref="IsSizeAlwaysRelative"/>
  582. /// <seealso cref="AxisX"/>
  583. /// </summary>
  584. /// <value>
  585. /// A Double value that represents the position of an annotation's right boundary.
  586. /// </value>
  587. /// <remarks>
  588. /// To use axes coordinates, anchor
  589. /// an annotation to a data point using the <see cref="AnchorDataPoint"/> property, or
  590. /// set the annotation axes using the <see cref="AxisX"/> or <see cref="AxisY"/> properties
  591. /// and set the <see cref="IsSizeAlwaysRelative"/> property to <b>false</b>.
  592. /// </remarks>
  593. [
  594. SRCategory("CategoryAttributePosition"),
  595. DefaultValue(double.NaN),
  596. SRDescription("DescriptionAttributeRight3"),
  597. RefreshPropertiesAttribute(RefreshProperties.All),
  598. Browsable(false),
  599. DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
  600. SerializationVisibilityAttribute(SerializationVisibility.Hidden),
  601. TypeConverter(typeof(DoubleNanValueConverter)),
  602. ]
  603. virtual public double Right
  604. {
  605. get
  606. {
  607. return _x + _width;
  608. }
  609. set
  610. {
  611. _width = value - _x;
  612. this.ResetCurrentRelativePosition();
  613. Invalidate();
  614. }
  615. }
  616. /// <summary>
  617. /// Gets or sets an annotation position's bottom boundary.
  618. /// <seealso cref="IsSizeAlwaysRelative"/>
  619. /// <seealso cref="AxisX"/>
  620. /// </summary>
  621. /// <value>
  622. /// A Double value that represents the position of an annotation's bottom boundary.
  623. /// </value>
  624. /// <remarks>
  625. /// To use axes coordinates, anchor
  626. /// an annotation to a data point using the <see cref="AnchorDataPoint"/> property, or
  627. /// set the annotation axes using the <see cref="AxisX"/> or <see cref="AxisY"/> properties
  628. /// and set the <see cref="IsSizeAlwaysRelative"/> property to <b>false</b>.
  629. /// </remarks>
  630. [
  631. SRCategory("CategoryAttributePosition"),
  632. DefaultValue(double.NaN),
  633. SRDescription("DescriptionAttributeBottom"),
  634. RefreshPropertiesAttribute(RefreshProperties.All),
  635. Browsable(false),
  636. DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
  637. SerializationVisibilityAttribute(SerializationVisibility.Hidden),
  638. TypeConverter(typeof(DoubleNanValueConverter)),
  639. ]
  640. virtual public double Bottom
  641. {
  642. get
  643. {
  644. return _y + _height;
  645. }
  646. set
  647. {
  648. _height = value - _y;
  649. this.ResetCurrentRelativePosition();
  650. Invalidate();
  651. }
  652. }
  653. #endregion
  654. #region Visual Attributes
  655. /// <summary>
  656. /// Gets or sets a flag that determines if an annotation is selected.
  657. /// <seealso cref="AllowSelecting"/>
  658. /// </summary>
  659. /// <value>
  660. /// <b>True</b> if the annotation is selected, <b>false</b> otherwise.
  661. /// </value>
  662. [
  663. SRCategory("CategoryAttributeAppearance"),
  664. DefaultValue(false),
  665. Browsable(false),
  666. SRDescription("DescriptionAttributeSelected"),
  667. ]
  668. virtual public bool IsSelected
  669. {
  670. get
  671. {
  672. return _isSelected;
  673. }
  674. set
  675. {
  676. _isSelected = value;
  677. Invalidate();
  678. }
  679. }
  680. /// <summary>
  681. /// Gets or sets an annotation selection points style.
  682. /// </summary>
  683. /// <value>
  684. /// A <see cref="SelectionPointsStyle"/> value that represents annotation
  685. /// selection style.
  686. /// </value>
  687. /// <remarks>
  688. /// This property is for internal use and is hidden at design and run time.
  689. /// </remarks>
  690. [
  691. SRCategory("CategoryAttributeAppearance"),
  692. DefaultValue(SelectionPointsStyle.Rectangle),
  693. ParenthesizePropertyNameAttribute(true),
  694. Browsable(false),
  695. EditorBrowsableAttribute(EditorBrowsableState.Never),
  696. DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
  697. SerializationVisibilityAttribute(SerializationVisibility.Hidden),
  698. SRDescription("DescriptionAttributeSelectionPointsStyle"),
  699. ]
  700. virtual internal SelectionPointsStyle SelectionPointsStyle
  701. {
  702. get
  703. {
  704. return SelectionPointsStyle.Rectangle;
  705. }
  706. }
  707. /// <summary>
  708. /// Gets or sets a flag that specifies whether an annotation is visible.
  709. /// </summary>
  710. /// <value>
  711. /// <b>True</b> if the annotation is visible, <b>false</b> otherwise.
  712. /// </value>
  713. [
  714. SRCategory("CategoryAttributeAppearance"),
  715. DefaultValue(true),
  716. SRDescription("DescriptionAttributeVisible"),
  717. ParenthesizePropertyNameAttribute(true),
  718. ]
  719. virtual public bool Visible
  720. {
  721. get
  722. {
  723. return _visible;
  724. }
  725. set
  726. {
  727. _visible = value;
  728. Invalidate();
  729. CallOnModifing();
  730. }
  731. }
  732. /// <summary>
  733. /// Gets or sets an annotation's content alignment.
  734. /// </summary>
  735. /// <value>
  736. /// A <see cref="ContentAlignment"/> value that represents the content alignment.
  737. /// </value>
  738. /// <remarks>
  739. /// This property is used to align text for <see cref="TextAnnotation"/>, <see cref="RectangleAnnotation"/>,
  740. /// <see cref="EllipseAnnotation"/> and <see cref="CalloutAnnotation"/> objects, and to align
  741. /// a non-scaled image inside an <see cref="ImageAnnotation"/> object.
  742. /// </remarks>
  743. [
  744. SRCategory("CategoryAttributeAppearance"),
  745. DefaultValue(typeof(ContentAlignment), "MiddleCenter"),
  746. SRDescription("DescriptionAttributeAlignment"),
  747. ]
  748. virtual public ContentAlignment Alignment
  749. {
  750. get
  751. {
  752. return _alignment;
  753. }
  754. set
  755. {
  756. _alignment = value;
  757. Invalidate();
  758. CallOnModifing();
  759. }
  760. }
  761. /// <summary>
  762. /// Gets or sets the text color of an annotation.
  763. /// <seealso cref="Font"/>
  764. /// </summary>
  765. /// <value>
  766. /// A <see cref="Color"/> value used for the text color of an annotation.
  767. /// </value>
  768. [
  769. SRCategory("CategoryAttributeAppearance"),
  770. DefaultValue(typeof(Color), "Black"),
  771. SRDescription("DescriptionAttributeForeColor"),
  772. TypeConverter(typeof(ColorConverter)),
  773. #if DESIGNER
  774. Editor(typeof(ChartColorEditor), typeof(UITypeEditor))
  775. #endif
  776. ]
  777. virtual public Color ForeColor
  778. {
  779. get
  780. {
  781. return _foreColor;
  782. }
  783. set
  784. {
  785. _foreColor = value;
  786. Invalidate();
  787. CallOnModifing();
  788. }
  789. }
  790. /// <summary>
  791. /// Gets or sets the font of an annotation's text.
  792. /// <seealso cref="ForeColor"/>
  793. /// </summary>
  794. /// <value>
  795. /// A <see cref="Font"/> object used for an annotation's text.
  796. /// </value>
  797. [
  798. SRCategory("CategoryAttributeAppearance"),
  799. DefaultValue(typeof(Font), "Microsoft Sans Serif, 8pt"),
  800. SRDescription("DescriptionAttributeTextFont"),
  801. ]
  802. virtual public Font Font
  803. {
  804. get
  805. {
  806. return _textFont;
  807. }
  808. set
  809. {
  810. _textFont = value;
  811. this.Invalidate();
  812. CallOnModifing();
  813. }
  814. }
  815. /// <summary>
  816. /// Gets or sets an annotation's text style.
  817. /// <seealso cref="Font"/>
  818. /// <seealso cref="ForeColor"/>
  819. /// </summary>
  820. /// <value>
  821. /// A <see cref="TextStyle"/> value used to draw an annotation's text.
  822. /// </value>
  823. [
  824. SRCategory("CategoryAttributeAppearance"),
  825. DefaultValue(typeof(TextStyle), "Default"),
  826. SRDescription("DescriptionAttributeTextStyle"),
  827. ]
  828. virtual public TextStyle TextStyle
  829. {
  830. get
  831. {
  832. return _textStyle;
  833. }
  834. set
  835. {
  836. _textStyle = value;
  837. Invalidate();
  838. CallOnModifing();
  839. }
  840. }
  841. /// <summary>
  842. /// Gets or sets the color of an annotation line.
  843. /// <seealso cref="LineWidth"/>
  844. /// <seealso cref="LineDashStyle"/>
  845. /// </summary>
  846. /// <value>
  847. /// A <see cref="Color"/> value used to draw an annotation line.
  848. /// </value>
  849. [
  850. SRCategory("CategoryAttributeAppearance"),
  851. DefaultValue(typeof(Color), "Black"),
  852. SRDescription("DescriptionAttributeLineColor"),
  853. TypeConverter(typeof(ColorConverter)),
  854. #if DESIGNER
  855. Editor(typeof(ChartColorEditor), typeof(UITypeEditor))
  856. #endif
  857. ]
  858. virtual public Color LineColor
  859. {
  860. get
  861. {
  862. return lineColor;
  863. }
  864. set
  865. {
  866. lineColor = value;
  867. Invalidate();
  868. CallOnModifing();
  869. }
  870. }
  871. /// <summary>
  872. /// Gets or sets the width of an annotation line.
  873. /// <seealso cref="LineColor"/>
  874. /// <seealso cref="LineDashStyle"/>
  875. /// </summary>
  876. /// <value>
  877. /// An integer value defining the width of an annotation line in pixels.
  878. /// </value>
  879. [
  880. SRCategory("CategoryAttributeAppearance"),
  881. DefaultValue(1),
  882. SRDescription("DescriptionAttributeLineWidth"),
  883. ]
  884. virtual public int LineWidth
  885. {
  886. get
  887. {
  888. return _lineWidth;
  889. }
  890. set
  891. {
  892. if (value < 0)
  893. {
  894. throw (new ArgumentOutOfRangeException("value", SR.ExceptionAnnotationLineWidthIsNegative));
  895. }
  896. _lineWidth = value;
  897. Invalidate();
  898. CallOnModifing();
  899. }
  900. }
  901. /// <summary>
  902. /// Gets or sets the style of an annotation line.
  903. /// <seealso cref="LineWidth"/>
  904. /// <seealso cref="LineColor"/>
  905. /// </summary>
  906. /// <value>
  907. /// A <see cref="ChartDashStyle"/> value used to draw an annotation line.
  908. /// </value>
  909. [
  910. SRCategory("CategoryAttributeAppearance"),
  911. DefaultValue(ChartDashStyle.Solid),
  912. SRDescription("DescriptionAttributeLineDashStyle"),
  913. ]
  914. virtual public ChartDashStyle LineDashStyle
  915. {
  916. get
  917. {
  918. return _lineDashStyle;
  919. }
  920. set
  921. {
  922. _lineDashStyle = value;
  923. Invalidate();
  924. CallOnModifing();
  925. }
  926. }
  927. /// <summary>
  928. /// Gets or sets the background color of an annotation.
  929. /// <seealso cref="BackSecondaryColor"/>
  930. /// <seealso cref="BackHatchStyle"/>
  931. /// <seealso cref="BackGradientStyle"/>
  932. /// </summary>
  933. /// <value>
  934. /// A <see cref="Color"/> value used for the background of an annotation.
  935. /// </value>
  936. [
  937. SRCategory("CategoryAttributeAppearance"),
  938. DefaultValue(typeof(Color), ""),
  939. SRDescription("DescriptionAttributeBackColor"),
  940. NotifyParentPropertyAttribute(true),
  941. TypeConverter(typeof(ColorConverter)),
  942. #if DESIGNER
  943. Editor(typeof(ChartColorEditor), typeof(UITypeEditor))
  944. #endif
  945. ]
  946. virtual public Color BackColor
  947. {
  948. get
  949. {
  950. return _backColor;
  951. }
  952. set
  953. {
  954. _backColor = value;
  955. Invalidate();
  956. CallOnModifing();
  957. }
  958. }
  959. /// <summary>
  960. /// Gets or sets the background hatch style of an annotation.
  961. /// <seealso cref="BackSecondaryColor"/>
  962. /// <seealso cref="BackColor"/>
  963. /// <seealso cref="BackGradientStyle"/>
  964. /// </summary>
  965. /// <value>
  966. /// A <see cref="ChartHatchStyle"/> value used for the background of an annotation.
  967. /// </value>
  968. /// <remarks>
  969. /// Two colors are used to draw the hatching, <see cref="BackColor"/> and <see cref="BackSecondaryColor"/>.
  970. /// </remarks>
  971. [
  972. SRCategory("CategoryAttributeAppearance"),
  973. DefaultValue(ChartHatchStyle.None),
  974. NotifyParentPropertyAttribute(true),
  975. SRDescription("DescriptionAttributeBackHatchStyle"),
  976. #if DESIGNER
  977. Editor(typeof(HatchStyleEditor), typeof(UITypeEditor))
  978. #endif
  979. ]
  980. virtual public ChartHatchStyle BackHatchStyle
  981. {
  982. get
  983. {
  984. return _backHatchStyle;
  985. }
  986. set
  987. {
  988. _backHatchStyle = value;
  989. Invalidate();
  990. CallOnModifing();
  991. }
  992. }
  993. /// <summary>
  994. /// Gets or sets the background gradient style of an annotation.
  995. /// <seealso cref="BackSecondaryColor"/>
  996. /// <seealso cref="BackColor"/>
  997. /// <seealso cref="BackHatchStyle"/>
  998. /// </summary>
  999. /// <value>
  1000. /// A <see cref="GradientStyle"/> value used for the background of an annotation.
  1001. /// </value>
  1002. /// <remarks>
  1003. /// Two colors are used to draw the gradient, <see cref="BackColor"/> and <see cref="BackSecondaryColor"/>.
  1004. /// </remarks>
  1005. [
  1006. SRCategory("CategoryAttributeAppearance"),
  1007. DefaultValue(GradientStyle.None),
  1008. NotifyParentPropertyAttribute(true),
  1009. SRDescription("DescriptionAttributeBackGradientStyle"),
  1010. #if DESIGNER
  1011. Editor(typeof(GradientEditor), typeof(UITypeEditor))
  1012. #endif
  1013. ]
  1014. virtual public GradientStyle BackGradientStyle
  1015. {
  1016. get
  1017. {
  1018. return _backGradientStyle;
  1019. }
  1020. set
  1021. {
  1022. _backGradientStyle = value;
  1023. Invalidate();
  1024. CallOnModifing();
  1025. }
  1026. }
  1027. /// <summary>
  1028. /// Gets or sets the secondary background color of an annotation.
  1029. /// <seealso cref="BackColor"/>
  1030. /// <seealso cref="BackHatchStyle"/>
  1031. /// <seealso cref="BackGradientStyle"/>
  1032. /// </summary>
  1033. /// <value>
  1034. /// A <see cref="Color"/> value used for the secondary color of an annotation background with
  1035. /// hatching or gradient fill.
  1036. /// </value>
  1037. /// <remarks>
  1038. /// This color is used with <see cref="BackColor"/> when <see cref="BackHatchStyle"/> or
  1039. /// <see cref="BackGradientStyle"/> are used.
  1040. /// </remarks>
  1041. [
  1042. SRCategory("CategoryAttributeAppearance"),
  1043. DefaultValue(typeof(Color), ""),
  1044. NotifyParentPropertyAttribute(true),
  1045. SRDescription("DescriptionAttributeBackSecondaryColor"),
  1046. TypeConverter(typeof(ColorConverter)),
  1047. #if DESIGNER
  1048. Editor(typeof(ChartColorEditor), typeof(UITypeEditor))
  1049. #endif
  1050. ]
  1051. virtual public Color BackSecondaryColor
  1052. {
  1053. get
  1054. {
  1055. return _backSecondaryColor;
  1056. }
  1057. set
  1058. {
  1059. _backSecondaryColor = value;
  1060. Invalidate();
  1061. CallOnModifing();
  1062. }
  1063. }
  1064. /// <summary>
  1065. /// Gets or sets the color of an annotation's shadow.
  1066. /// <seealso cref="ShadowOffset"/>
  1067. /// </summary>
  1068. /// <value>
  1069. /// A <see cref="Color"/> value used to draw an annotation's shadow.
  1070. /// </value>
  1071. [
  1072. SRCategory("CategoryAttributeAppearance"),
  1073. DefaultValue(typeof(Color), "128,0,0,0"),
  1074. SRDescription("DescriptionAttributeShadowColor"),
  1075. TypeConverter(typeof(ColorConverter)),
  1076. #if DESIGNER
  1077. Editor(typeof(ChartColorEditor), typeof(UITypeEditor))
  1078. #endif
  1079. ]
  1080. virtual public Color ShadowColor
  1081. {
  1082. get
  1083. {
  1084. return _shadowColor;
  1085. }
  1086. set
  1087. {
  1088. _shadowColor = value;
  1089. Invalidate();
  1090. CallOnModifing();
  1091. }
  1092. }
  1093. /// <summary>
  1094. /// Gets or sets the offset between an annotation and its shadow.
  1095. /// <seealso cref="ShadowColor"/>
  1096. /// </summary>
  1097. /// <value>
  1098. /// An integer value that represents the offset between an annotation and its shadow.
  1099. /// </value>
  1100. [
  1101. SRCategory("CategoryAttributeAppearance"),
  1102. DefaultValue(0),
  1103. SRDescription("DescriptionAttributeShadowOffset"),
  1104. ]
  1105. virtual public int ShadowOffset
  1106. {
  1107. get
  1108. {
  1109. return _shadowOffset;
  1110. }
  1111. set
  1112. {
  1113. _shadowOffset = value;
  1114. Invalidate();
  1115. CallOnModifing();
  1116. }
  1117. }
  1118. #endregion
  1119. #region Axes Attaching
  1120. /// <summary>
  1121. /// Gets or sets the name of the X axis which an annotation is attached to.
  1122. /// </summary>
  1123. /// <value>
  1124. /// A string value that represents the name of the X axis which an annotation
  1125. /// is attached to.
  1126. /// </value>
  1127. /// <remarks>
  1128. /// This property is for internal use and is hidden at design and run time.
  1129. /// </remarks>
  1130. [
  1131. SRCategory("CategoryAttributeAnchorAxes"),
  1132. DefaultValue(""),
  1133. Browsable(false),
  1134. Bindable(false),
  1135. EditorBrowsableAttribute(EditorBrowsableState.Never),
  1136. SRDescription("DescriptionAttributeAxisXName"),
  1137. ]
  1138. virtual public string AxisXName
  1139. {
  1140. get
  1141. {
  1142. if (_axisXName.Length == 0 && _axisX != null)
  1143. {
  1144. _axisXName = GetAxisName(_axisX);
  1145. }
  1146. return _axisXName;
  1147. }
  1148. set
  1149. {
  1150. _axisXName = value;
  1151. _axisX = null;
  1152. this.ResetCurrentRelativePosition();
  1153. Invalidate();
  1154. }
  1155. }
  1156. /// <summary>
  1157. /// Gets or sets the name of the Y axis which an annotation is attached to.
  1158. /// </summary>
  1159. /// <value>
  1160. /// A string value that represents the name of the Y axis which an annotation
  1161. /// is attached to.
  1162. /// </value>
  1163. /// <remarks>
  1164. /// This property is for internal use and is hidden at design and run time.
  1165. /// </remarks>
  1166. [
  1167. SRCategory("CategoryAttributeAnchorAxes"),
  1168. Browsable(false),
  1169. Bindable(false),
  1170. EditorBrowsableAttribute(EditorBrowsableState.Never),
  1171. DefaultValue(""),
  1172. SRDescription("DescriptionAttributeAxisYName"),
  1173. SerializationVisibilityAttribute(SerializationVisibility.Hidden),
  1174. ]
  1175. virtual public string AxisYName
  1176. {
  1177. get
  1178. {
  1179. // Always return empty string to prevent property serialization
  1180. // "YAxisName" property will be used instead.
  1181. return string.Empty;
  1182. }
  1183. set
  1184. {
  1185. this.YAxisName = value;
  1186. }
  1187. }
  1188. /// <summary>
  1189. /// Gets or sets the name of the Y axis which an annotation is attached to.
  1190. /// NOTE: "AxisYName" property was used before but the name was changed to solve the
  1191. /// duplicated hash value during the serialization with the "TitleSeparator" property.
  1192. /// </summary>
  1193. /// <value>
  1194. /// A string value that represents the name of the Y axis which an annotation
  1195. /// is attached to.
  1196. /// </value>
  1197. /// <remarks>
  1198. /// This property is for internal use and is hidden at design and run time.
  1199. /// </remarks>
  1200. [
  1201. SRCategory("CategoryAttributeAnchorAxes"),
  1202. Browsable(false),
  1203. Bindable(false),
  1204. EditorBrowsableAttribute(EditorBrowsableState.Never),
  1205. DefaultValue(""),
  1206. SRDescription("DescriptionAttributeAxisYName"),
  1207. ]
  1208. virtual public string YAxisName
  1209. {
  1210. get
  1211. {
  1212. if (_axisYName.Length == 0 && _axisY != null)
  1213. {
  1214. _axisYName = GetAxisName(_axisY);
  1215. }
  1216. return _axisYName;
  1217. }
  1218. set
  1219. {
  1220. _axisYName = value;
  1221. _axisY = null;
  1222. this.ResetCurrentRelativePosition();
  1223. Invalidate();
  1224. }
  1225. }
  1226. /// <summary>
  1227. /// Gets or sets the X axis which an annotation is attached to.
  1228. /// <seealso cref="AxisY"/>
  1229. /// <seealso cref="IsSizeAlwaysRelative"/>
  1230. /// </summary>
  1231. /// <value>
  1232. /// <see cref="Axis"/> object which an annotation is attached to.
  1233. /// </value>
  1234. /// <remarks>
  1235. /// When an annotation is attached to an axis, its X position is always in
  1236. /// axis coordinates. To define an annotation's size in axis coordinates as well,
  1237. /// make sure the <see cref="IsSizeAlwaysRelative"/> property is set to <b>false</b>.
  1238. /// <para>
  1239. /// Set this value to <b>null</b> or <b>nothing</b> to disable attachment to the axis.
  1240. /// </para>
  1241. /// </remarks>
  1242. [
  1243. SRCategory("CategoryAttributeAnchorAxes"),
  1244. DefaultValue(null),
  1245. DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
  1246. SerializationVisibilityAttribute(SerializationVisibility.Hidden),
  1247. SRDescription("DescriptionAttributeAxisX"),
  1248. #if DESIGNER
  1249. Editor(typeof(AnnotationAxisUITypeEditor), typeof(UITypeEditor)),
  1250. #endif
  1251. TypeConverter(typeof(AnnotationAxisValueConverter)),
  1252. ]
  1253. virtual public Axis AxisX
  1254. {
  1255. get
  1256. {
  1257. if (_axisX == null && _axisXName.Length > 0)
  1258. {
  1259. _axisX = GetAxisByName(_axisXName);
  1260. }
  1261. return _axisX;
  1262. }
  1263. set
  1264. {
  1265. _axisX = value;
  1266. _axisXName = String.Empty;
  1267. this.ResetCurrentRelativePosition();
  1268. Invalidate();
  1269. CallOnModifing();
  1270. }
  1271. }
  1272. /// <summary>
  1273. /// Gets or sets the Y axis which an annotation is attached to.
  1274. /// <seealso cref="AxisX"/>
  1275. /// <seealso cref="IsSizeAlwaysRelative"/>
  1276. /// </summary>
  1277. /// <value>
  1278. /// <see cref="Axis"/> object which an annotation is attached to.
  1279. /// </value>
  1280. /// <remarks>
  1281. /// When an annotation is attached to an axis, its Y position is always in
  1282. /// axis coordinates. To define an annotation's size in axis coordinates as well,
  1283. /// make sure <see cref="IsSizeAlwaysRelative"/> property is set to <b>false</b>.
  1284. /// <para>
  1285. /// Set this value to <b>null</b> or <b>nothing</b> to disable annotation attachment to an axis.
  1286. /// </para>
  1287. /// </remarks>
  1288. [
  1289. SRCategory("CategoryAttributeAnchorAxes"),
  1290. DefaultValue(null),
  1291. DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
  1292. SerializationVisibilityAttribute(SerializationVisibility.Hidden),
  1293. SRDescription("DescriptionAttributeAxisY"),
  1294. #if DESIGNER
  1295. Editor(typeof(AnnotationAxisUITypeEditor), typeof(UITypeEditor)),
  1296. #endif
  1297. TypeConverter(typeof(AnnotationAxisValueConverter)),
  1298. ]
  1299. virtual public Axis AxisY
  1300. {
  1301. get
  1302. {
  1303. if (_axisY == null && _axisYName.Length > 0)
  1304. {
  1305. _axisY = GetAxisByName(_axisYName);
  1306. }
  1307. return _axisY;
  1308. }
  1309. set
  1310. {
  1311. _axisY = value;
  1312. _axisYName = String.Empty;
  1313. this.ResetCurrentRelativePosition();
  1314. Invalidate();
  1315. CallOnModifing();
  1316. }
  1317. }
  1318. #endregion
  1319. #region Anchor
  1320. /// <summary>
  1321. /// Gets or sets the name of a data point which an annotation is anchored to.
  1322. /// </summary>
  1323. /// <value>
  1324. /// A string value that represents the name of the data point which an
  1325. /// annotation is anchored to.
  1326. /// </value>
  1327. /// <remarks>
  1328. /// This property is for internal use and is hidden at design and run time.
  1329. /// </remarks>
  1330. [
  1331. SRCategory("CategoryAttributeAnchor"),
  1332. Browsable(false),
  1333. Bindable(false),
  1334. EditorBrowsableAttribute(EditorBrowsableState.Never),
  1335. DefaultValue(""),
  1336. SRDescription("DescriptionAttributeAnchorDataPointName"),
  1337. ]
  1338. virtual public string AnchorDataPointName
  1339. {
  1340. get
  1341. {
  1342. if (_anchorDataPointName.Length == 0 && _anchorDataPoint != null)
  1343. {
  1344. _anchorDataPointName = GetDataPointName(_anchorDataPoint);
  1345. }
  1346. return _anchorDataPointName;
  1347. }
  1348. set
  1349. {
  1350. _anchorDataPointName = value;
  1351. _anchorDataPoint = null;
  1352. this.ResetCurrentRelativePosition();
  1353. Invalidate();
  1354. }
  1355. }
  1356. /// <summary>
  1357. /// Gets or sets the data point an annotation is anchored to.
  1358. /// <seealso cref="AnchorAlignment"/>
  1359. /// <seealso cref="AnchorOffsetX"/>
  1360. /// <seealso cref="AnchorOffsetY"/>
  1361. /// <seealso cref="AnchorX"/>
  1362. /// <seealso cref="AnchorY"/>
  1363. /// <seealso cref="SetAnchor(Charting.DataPoint)"/>
  1364. /// <seealso cref="SetAnchor(Charting.DataPoint, Charting.DataPoint)"/>
  1365. /// </summary>
  1366. /// <value>
  1367. /// A <see cref="DataPoint"/> object an annotation is anchored to.
  1368. /// </value>
  1369. /// <remarks>
  1370. /// The annotation is anchored to the X and Y values of the specified data point,
  1371. /// and automatically uses the same axes coordinates as the data point.
  1372. /// <para>
  1373. /// To automatically position an annotation relative to an anchor point, make sure
  1374. /// its <see cref="X"/> and <see cref="Y"/> properties are set to <b>Double.NaN</b>.
  1375. /// The <see cref="AnchorAlignment"/> property may be used to change an annotation's
  1376. /// automatic position alignment to an anchor point. The <see cref="AnchorOffsetX"/> and
  1377. /// <see cref="AnchorOffsetY"/> properties may be used to add extra spacing.
  1378. /// </para>
  1379. /// <para>
  1380. /// When using this property, make sure the <see cref="AnchorX"/> and <see cref="AnchorY"/>
  1381. /// properties are set to <b>Double.NaN</b> (they have precedence).
  1382. /// </para>
  1383. /// <para>
  1384. /// Set this value to <b>null</b> or <b>nothing</b> to disable annotation anchoring to a data point.
  1385. /// </para>
  1386. /// </remarks>
  1387. [
  1388. SRCategory("CategoryAttributeAnchor"),
  1389. DefaultValue(null),
  1390. DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
  1391. SerializationVisibilityAttribute(SerializationVisibility.Hidden),
  1392. SRDescription("DescriptionAttributeAnchorDataPoint"),
  1393. #if DESIGNER
  1394. Editor(typeof(AnchorPointUITypeEditor), typeof(UITypeEditor)),
  1395. #endif
  1396. TypeConverter(typeof(AnchorPointValueConverter)),
  1397. ]
  1398. virtual public DataPoint AnchorDataPoint
  1399. {
  1400. get
  1401. {
  1402. if (_anchorDataPoint == null && _anchorDataPointName.Length > 0)
  1403. {
  1404. _anchorDataPoint = GetDataPointByName(_anchorDataPointName);
  1405. }
  1406. return _anchorDataPoint;
  1407. }
  1408. set
  1409. {
  1410. _anchorDataPoint = value;
  1411. _anchorDataPointName = String.Empty;
  1412. this.ResetCurrentRelativePosition();
  1413. Invalidate();
  1414. CallOnModifing();
  1415. }
  1416. }
  1417. /// <summary>
  1418. /// Gets or sets the X coordinate the annotation is anchored to.
  1419. /// <seealso cref="AnchorY"/>
  1420. /// <seealso cref="AnchorOffsetX"/>
  1421. /// <seealso cref="AnchorOffsetY"/>
  1422. /// <seealso cref="AnchorAlignment"/>
  1423. /// <seealso cref="AnchorDataPoint"/>
  1424. /// </summary>
  1425. /// <value>
  1426. /// A double value that represents the X coordinate which an annotation is anchored to.
  1427. /// </value>
  1428. /// <remarks>
  1429. /// The annotation is anchored to the X coordinate specified in relative or axis coordinates,
  1430. /// depending on the <see cref="AxisX"/> property value.
  1431. /// <para>
  1432. /// To automatically position an annotation relative to an anchor point, make sure
  1433. /// its <see cref="X"/> property is set to <b>Double.NaN</b>.
  1434. /// The <see cref="AnchorAlignment"/> property may be used to change the annotation's
  1435. /// automatic position alignment to the anchor point. The <see cref="AnchorOffsetX"/> and
  1436. /// <see cref="AnchorOffsetY"/> properties may be used to add extra spacing.
  1437. /// </para>
  1438. /// <para>
  1439. /// This property has a higher priority than the <see cref="AnchorDataPoint"/> property.
  1440. /// </para>
  1441. /// <para>
  1442. /// Set this value to <b>Double.NaN</b> to disable annotation anchoring to the value.
  1443. /// </para>
  1444. /// </remarks>
  1445. [
  1446. SRCategory("CategoryAttributeAnchor"),
  1447. DefaultValue(double.NaN),
  1448. SRDescription("DescriptionAttributeAnchorX"),
  1449. RefreshPropertiesAttribute(RefreshProperties.All),
  1450. TypeConverter(typeof(DoubleNanValueConverter)),
  1451. ]
  1452. virtual public double AnchorX
  1453. {
  1454. get
  1455. {
  1456. return _anchorX;
  1457. }
  1458. set
  1459. {
  1460. _anchorX = value;
  1461. this.ResetCurrentRelativePosition();
  1462. Invalidate();
  1463. CallOnModifing();
  1464. }
  1465. }
  1466. /// <summary>
  1467. /// Gets or sets the Y coordinate which an annotation is anchored to.
  1468. /// <seealso cref="AnchorY"/>
  1469. /// <seealso cref="AnchorOffsetX"/>
  1470. /// <seealso cref="AnchorOffsetY"/>
  1471. /// <seealso cref="AnchorAlignment"/>
  1472. /// <seealso cref="AnchorDataPoint"/>
  1473. /// </summary>
  1474. /// <value>
  1475. /// A double value that represents the Y coordinate which an annotation is anchored to.
  1476. /// </value>
  1477. /// <remarks>
  1478. /// The annotation is anchored to the Y coordinate specified in relative or axis coordinates,
  1479. /// depending on the <see cref="AxisX"/> property value.
  1480. /// <para>
  1481. /// To automatically position an annotation relative to an anchor point, make sure
  1482. /// its <see cref="Y"/> property is set to <b>Double.NaN</b>.
  1483. /// The <see cref="AnchorAlignment"/> property may be used to change the annotation's
  1484. /// automatic position alignment to the anchor point. The <see cref="AnchorOffsetX"/> and
  1485. /// <see cref="AnchorOffsetY"/> properties may be used to add extra spacing.
  1486. /// </para>
  1487. /// <para>
  1488. /// This property has a higher priority than the <see cref="AnchorDataPoint"/> property.
  1489. /// </para>
  1490. /// <para>
  1491. /// Set this value to <b>Double.NaN</b> to disable annotation anchoring to the value.
  1492. /// </para>
  1493. /// </remarks>
  1494. [
  1495. SRCategory("CategoryAttributeAnchor"),
  1496. DefaultValue(double.NaN),
  1497. SRDescription("DescriptionAttributeAnchorY"),
  1498. RefreshPropertiesAttribute(RefreshProperties.All),
  1499. TypeConverter(typeof(DoubleNanValueConverter)),
  1500. ]
  1501. virtual public double AnchorY
  1502. {
  1503. get
  1504. {
  1505. return _anchorY;
  1506. }
  1507. set
  1508. {
  1509. _anchorY = value;
  1510. this.ResetCurrentRelativePosition();
  1511. Invalidate();
  1512. CallOnModifing();
  1513. }
  1514. }
  1515. /// <summary>
  1516. /// Gets or sets the x-coordinate offset between the positions of an annotation and its anchor point.
  1517. /// <seealso cref="AnchorOffsetY"/>
  1518. /// <seealso cref="AnchorDataPoint"/>
  1519. /// <seealso cref="AnchorX"/>
  1520. /// <seealso cref="AnchorAlignment"/>
  1521. /// </summary>
  1522. /// <value>
  1523. /// A double value that represents the x-coordinate offset between the positions of an annotation and its anchor point.
  1524. /// </value>
  1525. /// <remarks>
  1526. /// The annotation must be anchored using the <see cref="AnchorDataPoint"/> or
  1527. /// <see cref="AnchorX"/> properties, and its <see cref="X"/> property must be set
  1528. /// to <b>Double.NaN</b>.
  1529. /// </remarks>
  1530. [
  1531. SRCategory("CategoryAttributeAnchor"),
  1532. DefaultValue(0.0),
  1533. SRDescription("DescriptionAttributeAnchorOffsetX3"),
  1534. RefreshPropertiesAttribute(RefreshProperties.All),
  1535. ]
  1536. virtual public double AnchorOffsetX
  1537. {
  1538. get
  1539. {
  1540. return anchorOffsetX;
  1541. }
  1542. set
  1543. {
  1544. if (value > 100.0 || value < -100.0)
  1545. {
  1546. throw (new ArgumentOutOfRangeException("value", SR.ExceptionAnnotationAnchorOffsetInvalid));
  1547. }
  1548. anchorOffsetX = value;
  1549. this.ResetCurrentRelativePosition();
  1550. Invalidate();
  1551. CallOnModifing();
  1552. }
  1553. }
  1554. /// <summary>
  1555. /// Gets or sets the y-coordinate offset between the positions of an annotation and its anchor point.
  1556. /// <seealso cref="Annotation.AnchorOffsetX"/>
  1557. /// <seealso cref="Annotation.AnchorDataPoint"/>
  1558. /// <seealso cref="Annotation.AnchorY"/>
  1559. /// <seealso cref="Annotation.AnchorAlignment"/>
  1560. /// </summary>
  1561. /// <value>
  1562. /// A double value that represents the y-coordinate offset between the positions of an annotation and its anchor point.
  1563. /// </value>
  1564. /// <remarks>
  1565. /// Annotation must be anchored using <see cref="Annotation.AnchorDataPoint"/> or
  1566. /// <see cref="Annotation.AnchorY"/> properties and it's <see cref="Annotation.Y"/> property must be set
  1567. /// to <b>Double.NaN</b>.
  1568. /// </remarks>
  1569. [
  1570. SRCategory("CategoryAttributeAnchor"),
  1571. DefaultValue(0.0),
  1572. SRDescription("DescriptionAttributeAnchorOffsetY3"),
  1573. RefreshPropertiesAttribute(RefreshProperties.All),
  1574. ]
  1575. virtual public double AnchorOffsetY
  1576. {
  1577. get
  1578. {
  1579. return anchorOffsetY;
  1580. }
  1581. set
  1582. {
  1583. if (value > 100.0 || value < -100.0)
  1584. {
  1585. throw (new ArgumentOutOfRangeException("value", SR.ExceptionAnnotationAnchorOffsetInvalid));
  1586. }
  1587. anchorOffsetY = value;
  1588. this.ResetCurrentRelativePosition();
  1589. Invalidate();
  1590. CallOnModifing();
  1591. }
  1592. }
  1593. /// <summary>
  1594. /// Gets or sets an annotation position's alignment to the anchor point.
  1595. /// <seealso cref="AnchorX"/>
  1596. /// <seealso cref="AnchorY"/>
  1597. /// <seealso cref="AnchorDataPoint"/>
  1598. /// <seealso cref="AnchorOffsetX"/>
  1599. /// <seealso cref="AnchorOffsetY"/>
  1600. /// </summary>
  1601. /// <value>
  1602. /// A <see cref="ContentAlignment"/> value that represents the annotation's alignment to
  1603. /// the anchor point.
  1604. /// </value>
  1605. /// <remarks>
  1606. /// The annotation must be anchored using either <see cref="AnchorDataPoint"/>, or the <see cref="AnchorX"/>
  1607. /// and <see cref="AnchorY"/> properties. Its <see cref="X"/> and <see cref="Y"/>
  1608. /// properties must be set to <b>Double.NaN</b>.
  1609. /// </remarks>
  1610. [
  1611. SRCategory("CategoryAttributeAnchor"),
  1612. DefaultValue(typeof(ContentAlignment), "BottomCenter"),
  1613. SRDescription("DescriptionAttributeAnchorAlignment"),
  1614. ]
  1615. virtual public ContentAlignment AnchorAlignment
  1616. {
  1617. get
  1618. {
  1619. return anchorAlignment;
  1620. }
  1621. set
  1622. {
  1623. anchorAlignment = value;
  1624. this.ResetCurrentRelativePosition();
  1625. Invalidate();
  1626. CallOnModifing();
  1627. }
  1628. }
  1629. #endregion // Anchoring
  1630. #region Editing Permissions
  1631. /// <summary>
  1632. /// Gets or sets a flag that specifies whether an annotation may be selected
  1633. /// with a mouse by the end user.
  1634. /// </summary>
  1635. /// <value>
  1636. /// <b>True</b> if the annotation may be selected, <b>false</b> otherwise.
  1637. /// </value>
  1638. [
  1639. SRCategory("CategoryAttributeEditing"),
  1640. DefaultValue(false),
  1641. SRDescription("DescriptionAttributeAllowSelecting"),
  1642. ]
  1643. virtual public bool AllowSelecting
  1644. {
  1645. get
  1646. {
  1647. return _allowSelecting;
  1648. }
  1649. set
  1650. {
  1651. _allowSelecting = value;
  1652. CallOnModifing();
  1653. }
  1654. }
  1655. /// <summary>
  1656. /// Gets or sets a flag that specifies whether an annotation may be moved
  1657. /// with a mouse by the end user.
  1658. /// </summary>
  1659. /// <value>
  1660. /// <b>True</b> if the annotation may be moved, <b>false</b> otherwise.
  1661. /// </value>
  1662. [
  1663. SRCategory("CategoryAttributeEditing"),
  1664. DefaultValue(false),
  1665. SRDescription("DescriptionAttributeAllowMoving"),
  1666. ]
  1667. virtual public bool AllowMoving
  1668. {
  1669. get
  1670. {
  1671. return _allowMoving;
  1672. }
  1673. set
  1674. {
  1675. _allowMoving = value;
  1676. CallOnModifing();
  1677. }
  1678. }
  1679. /// <summary>
  1680. /// Gets or sets a flag that specifies whether an annotation anchor may be moved
  1681. /// with a mouse by the end user.
  1682. /// </summary>
  1683. /// <value>
  1684. /// <b>True</b> if the annotation anchor may be moved, <b>false</b> otherwise.
  1685. /// </value>
  1686. [
  1687. SRCategory("CategoryAttributeEditing"),
  1688. DefaultValue(false),
  1689. SRDescription("DescriptionAttributeAllowAnchorMoving3"),
  1690. ]
  1691. virtual public bool AllowAnchorMoving
  1692. {
  1693. get
  1694. {
  1695. return _allowAnchorMoving;
  1696. }
  1697. set
  1698. {
  1699. _allowAnchorMoving = value;
  1700. CallOnModifing();
  1701. }
  1702. }
  1703. /// <summary>
  1704. /// Gets or sets a flag that specifies whether an annotation may be resized
  1705. /// with a mouse by the end user.
  1706. /// </summary>
  1707. /// <value>
  1708. /// <b>True</b> if the annotation may be resized, <b>false</b> otherwise.
  1709. /// </value>
  1710. [
  1711. SRCategory("CategoryAttributeEditing"),
  1712. DefaultValue(false),
  1713. SRDescription("DescriptionAttributeAllowResizing"),
  1714. ]
  1715. virtual public bool AllowResizing
  1716. {
  1717. get
  1718. {
  1719. return _allowResizing;
  1720. }
  1721. set
  1722. {
  1723. _allowResizing = value;
  1724. CallOnModifing();
  1725. }
  1726. }
  1727. /// <summary>
  1728. /// Gets or sets a flag that specifies whether an annotation's text may be edited
  1729. /// when the end user double clicks on the text.
  1730. /// </summary>
  1731. /// <value>
  1732. /// <b>True</b> if the annotation text may be edited, <b>false</b> otherwise.
  1733. /// </value>
  1734. [
  1735. SRCategory("CategoryAttributeEditing"),
  1736. DefaultValue(false),
  1737. SRDescription("DescriptionAttributeAllowTextEditing"),
  1738. ]
  1739. virtual public bool AllowTextEditing
  1740. {
  1741. get
  1742. {
  1743. return _allowTextEditing;
  1744. }
  1745. set
  1746. {
  1747. _allowTextEditing = value;
  1748. CallOnModifing();
  1749. }
  1750. }
  1751. /// <summary>
  1752. /// Gets or sets a flag that specifies whether a polygon annotation's points
  1753. /// may be moved with a mouse by the end user.
  1754. /// </summary>
  1755. /// <value>
  1756. /// <b>True</b> if the polygon annotation's points may be moved, <b>false</b> otherwise.
  1757. /// </value>
  1758. [
  1759. SRCategory("CategoryAttributeEditing"),
  1760. DefaultValue(false),
  1761. SRDescription("DescriptionAttributeAllowPathEditing3"),
  1762. ]
  1763. virtual public bool AllowPathEditing
  1764. {
  1765. get
  1766. {
  1767. return _allowPathEditing;
  1768. }
  1769. set
  1770. {
  1771. _allowPathEditing = value;
  1772. CallOnModifing();
  1773. }
  1774. }
  1775. #endregion
  1776. #region Interactivity
  1777. /// <summary>
  1778. /// Gets or sets an annotation's tooltip text.
  1779. /// </summary>
  1780. /// <value>
  1781. /// A string value.
  1782. /// </value>
  1783. /// <remarks>
  1784. /// Special keywords can be used in the text when an annotation is anchored to
  1785. /// a data point using the <see cref="AnchorDataPoint"/> property. For a listing of
  1786. /// these keywords, refer to the "Annotations" help topic.
  1787. /// </remarks>
  1788. [
  1789. SRCategory("CategoryAttributeMisc"),
  1790. DefaultValue(""),
  1791. SRDescription("DescriptionAttributeToolTip"),
  1792. ]
  1793. virtual public string ToolTip
  1794. {
  1795. get
  1796. {
  1797. return _tooltip;
  1798. }
  1799. set
  1800. {
  1801. _tooltip = value;
  1802. CallOnModifing();
  1803. }
  1804. }
  1805. #endregion // Interactivity
  1806. #endregion
  1807. #region Methods
  1808. #region Painting
  1809. /// <summary>
  1810. /// Paints the annotation object using the specified graphics.
  1811. /// </summary>
  1812. /// <param name="graphics">
  1813. /// A <see cref="ChartGraphics"/> object used to paint the annotation object.
  1814. /// </param>
  1815. /// <param name="chart">
  1816. /// Reference to the annotation's <see cref="Chart"/> control owner.
  1817. /// </param>
  1818. abstract internal void Paint(Chart chart, ChartGraphics graphics);
  1819. /// <summary>
  1820. /// Paints annotation selection markers.
  1821. /// </summary>
  1822. /// <param name="chartGraphics">Chart graphics used for painting.</param>
  1823. /// <param name="rect">Selection rectangle.</param>
  1824. /// <param name="path">Selection path.</param>
  1825. virtual internal void PaintSelectionHandles(ChartGraphics chartGraphics, RectangleF rect, GraphicsPath path)
  1826. {
  1827. // Define markers appearance style
  1828. Color markerBorderColor = Color.Black;
  1829. Color markerColor = Color.FromArgb(200, 255, 255, 255);
  1830. MarkerStyle markerStyle = MarkerStyle.Square;
  1831. int markerSize = selectionMarkerSize;
  1832. Boolean selected = this.IsSelected;
  1833. SizeF markerSizeRel = chartGraphics.GetRelativeSize(new SizeF(markerSize, markerSize));
  1834. if (this.Common.ProcessModePaint &&
  1835. !this.Common.ChartPicture.isPrinting)
  1836. {
  1837. // Clear selection rectangles
  1838. this.selectionRects = null;
  1839. // Check if annotation is selected
  1840. if (selected)
  1841. {
  1842. // Create selection rectangles
  1843. this.selectionRects = new RectangleF[9];
  1844. // Draw selection handles for single dimension annotations like line.
  1845. if (this.SelectionPointsStyle == SelectionPointsStyle.TwoPoints)
  1846. {
  1847. // Save selection handles position in array elements 0 and 4
  1848. this.selectionRects[(int)ResizingMode.TopLeftHandle] = new RectangleF(
  1849. rect.X - markerSizeRel.Width / 2f,
  1850. rect.Y - markerSizeRel.Height / 2f,
  1851. markerSizeRel.Width,
  1852. markerSizeRel.Height);
  1853. this.selectionRects[(int)ResizingMode.BottomRightHandle] = new RectangleF(
  1854. rect.Right - markerSizeRel.Width / 2f,
  1855. rect.Bottom - markerSizeRel.Height / 2f,
  1856. markerSizeRel.Width,
  1857. markerSizeRel.Height);
  1858. // Draw selection handle
  1859. chartGraphics.DrawMarkerRel(
  1860. rect.Location,
  1861. markerStyle,
  1862. markerSize,
  1863. markerColor,
  1864. markerBorderColor,
  1865. 1,
  1866. "",
  1867. Color.Empty,
  1868. 0,
  1869. Color.FromArgb(128, 0, 0, 0),
  1870. RectangleF.Empty);
  1871. chartGraphics.DrawMarkerRel(
  1872. new PointF(rect.Right, rect.Bottom),
  1873. markerStyle,
  1874. markerSize,
  1875. markerColor,
  1876. markerBorderColor,
  1877. 1,
  1878. "",
  1879. Color.Empty,
  1880. 0,
  1881. Color.FromArgb(128, 0, 0, 0),
  1882. RectangleF.Empty);
  1883. }
  1884. else if (this.SelectionPointsStyle == SelectionPointsStyle.Rectangle)
  1885. {
  1886. for (int index = 0; index < 8; index++)
  1887. {
  1888. // Get handle position
  1889. PointF handlePosition = PointF.Empty;
  1890. switch ((ResizingMode)index)
  1891. {
  1892. case ResizingMode.TopLeftHandle:
  1893. handlePosition = rect.Location;
  1894. break;
  1895. case ResizingMode.TopHandle:
  1896. handlePosition = new PointF(rect.X + rect.Width / 2f, rect.Y);
  1897. break;
  1898. case ResizingMode.TopRightHandle:
  1899. handlePosition = new PointF(rect.Right, rect.Y);
  1900. break;
  1901. case ResizingMode.RightHandle:
  1902. handlePosition = new PointF(rect.Right, rect.Y + rect.Height / 2f);
  1903. break;
  1904. case ResizingMode.BottomRightHandle:
  1905. handlePosition = new PointF(rect.Right, rect.Bottom);
  1906. break;
  1907. case ResizingMode.BottomHandle:
  1908. handlePosition = new PointF(rect.X + rect.Width / 2f, rect.Bottom);
  1909. break;
  1910. case ResizingMode.BottomLeftHandle:
  1911. handlePosition = new PointF(rect.X, rect.Bottom);
  1912. break;
  1913. case ResizingMode.LeftHandle:
  1914. handlePosition = new PointF(rect.X, rect.Y + rect.Height / 2f);
  1915. break;
  1916. }
  1917. // Save selection handles position in array elements 0 and 4
  1918. this.selectionRects[index] = new RectangleF(
  1919. handlePosition.X - markerSizeRel.Width / 2f,
  1920. handlePosition.Y - markerSizeRel.Height / 2f,
  1921. markerSizeRel.Width,
  1922. markerSizeRel.Height);
  1923. // Draw selection handle
  1924. chartGraphics.DrawMarkerRel(
  1925. handlePosition,
  1926. markerStyle,
  1927. markerSize,
  1928. markerColor,
  1929. markerBorderColor,
  1930. 1,
  1931. "",
  1932. Color.Empty,
  1933. 0,
  1934. Color.FromArgb(128, 0, 0, 0),
  1935. RectangleF.Empty);
  1936. }
  1937. }
  1938. //********************************************************************
  1939. //** Draw anchor selection handle
  1940. //********************************************************************
  1941. // Get vertical and horizontal axis
  1942. Axis vertAxis = null;
  1943. Axis horizAxis = null;
  1944. GetAxes(ref vertAxis, ref horizAxis);
  1945. // Get anchor position
  1946. double anchorX = double.NaN;
  1947. double anchorY = double.NaN;
  1948. bool relativeX = false;
  1949. bool relativeY = false;
  1950. this.GetAnchorLocation(ref anchorX, ref anchorY, ref relativeX, ref relativeY);
  1951. // Convert anchor location to relative coordinates
  1952. if (!double.IsNaN(anchorX) && !double.IsNaN(anchorY))
  1953. {
  1954. if (!relativeX && horizAxis != null)
  1955. {
  1956. anchorX = horizAxis.ValueToPosition(anchorX);
  1957. }
  1958. if (!relativeY && vertAxis != null)
  1959. {
  1960. anchorY = vertAxis.ValueToPosition(anchorY);
  1961. }
  1962. // Apply 3D transforamtion if required
  1963. ChartArea chartArea = null;
  1964. if (horizAxis != null && horizAxis.ChartArea != null)
  1965. {
  1966. chartArea = horizAxis.ChartArea;
  1967. }
  1968. if (vertAxis != null && vertAxis.ChartArea != null)
  1969. {
  1970. chartArea = vertAxis.ChartArea;
  1971. }
  1972. if (chartArea != null &&
  1973. chartArea.Area3DStyle.Enable3D == true &&
  1974. !chartArea.chartAreaIsCurcular &&
  1975. chartArea.requireAxes &&
  1976. chartArea.matrix3D.IsInitialized())
  1977. {
  1978. // Get anotation Z coordinate (use scene depth or anchored point Z position)
  1979. float positionZ = chartArea.areaSceneDepth;
  1980. if (this.AnchorDataPoint != null && this.AnchorDataPoint.series != null)
  1981. {
  1982. float depth = 0f;
  1983. chartArea.GetSeriesZPositionAndDepth(
  1984. this.AnchorDataPoint.series,
  1985. out depth,
  1986. out positionZ);
  1987. positionZ += depth / 2f;
  1988. }
  1989. // Define 3D points of annotation object
  1990. Point3D[] annot3DPoints = new Point3D[1];
  1991. annot3DPoints[0] = new Point3D((float)anchorX, (float)anchorY, positionZ);
  1992. // Tranform cube coordinates
  1993. chartArea.matrix3D.TransformPoints(annot3DPoints);
  1994. // Get transformed coordinates
  1995. anchorX = annot3DPoints[0].X;
  1996. anchorY = annot3DPoints[0].Y;
  1997. }
  1998. // Save selection handles position in array elements 0 and 4
  1999. this.selectionRects[(int)ResizingMode.AnchorHandle] = new RectangleF(
  2000. (float)anchorX - markerSizeRel.Width / 2f,
  2001. (float)anchorY - markerSizeRel.Height / 2f,
  2002. markerSizeRel.Width,
  2003. markerSizeRel.Height);
  2004. // Draw circular selection handle
  2005. chartGraphics.DrawMarkerRel(
  2006. new PointF((float)anchorX, (float)anchorY),
  2007. MarkerStyle.Cross,
  2008. selectionMarkerSize + 3,
  2009. markerColor,
  2010. markerBorderColor,
  2011. 1,
  2012. "",
  2013. Color.Empty,
  2014. 0,
  2015. Color.FromArgb(128, 0, 0, 0),
  2016. RectangleF.Empty);
  2017. }
  2018. //********************************************************************
  2019. //** Draw path selection handles
  2020. //********************************************************************
  2021. if (path != null && AllowPathEditing)
  2022. {
  2023. // Create selection rectangles for each point
  2024. PointF[] pathPoints = path.PathPoints;
  2025. RectangleF[] newSelectionRects = new RectangleF[pathPoints.Length + 9];
  2026. // Copy previous rectangles (first nine elements)
  2027. for (int index = 0; index < this.selectionRects.Length; index++)
  2028. {
  2029. newSelectionRects[index] = this.selectionRects[index];
  2030. }
  2031. this.selectionRects = newSelectionRects;
  2032. // Loop through all points
  2033. for (int index = 0; index < pathPoints.Length; index++)
  2034. {
  2035. // Get handle position
  2036. PointF handlePosition = chartGraphics.GetRelativePoint(pathPoints[index]);
  2037. // Save selection handles position in array elements 0 and 4
  2038. this.selectionRects[9 + index] = new RectangleF(
  2039. handlePosition.X - markerSizeRel.Width / 2f,
  2040. handlePosition.Y - markerSizeRel.Height / 2f,
  2041. markerSizeRel.Width,
  2042. markerSizeRel.Height);
  2043. // Draw selection handle
  2044. chartGraphics.DrawMarkerRel(
  2045. handlePosition,
  2046. MarkerStyle.Circle,
  2047. selectionMarkerSize + 1,
  2048. markerColor,
  2049. markerBorderColor,
  2050. 1,
  2051. "",
  2052. Color.Empty,
  2053. 0,
  2054. Color.FromArgb(128, 0, 0, 0),
  2055. RectangleF.Empty);
  2056. }
  2057. }
  2058. }
  2059. }
  2060. }
  2061. #endregion
  2062. #region Position and Size
  2063. /// <summary>
  2064. /// Resizes an annotation according to its content size.
  2065. /// </summary>
  2066. /// <remarks>
  2067. /// Sets the annotation width and height to fit the specified text. This method applies to
  2068. /// <see cref="TextAnnotation"/>, <see cref="RectangleAnnotation"/>, <see cref="EllipseAnnotation"/>
  2069. /// and <see cref="CalloutAnnotation"/> objects only.
  2070. /// </remarks>
  2071. virtual public void ResizeToContent()
  2072. {
  2073. RectangleF position = GetContentPosition();
  2074. if (!double.IsNaN(position.Width))
  2075. {
  2076. this.Width = position.Width;
  2077. }
  2078. if (!double.IsNaN(position.Height))
  2079. {
  2080. this.Height = position.Height;
  2081. }
  2082. }
  2083. /// <summary>
  2084. /// Gets an annotation's content position.
  2085. /// </summary>
  2086. /// <returns>Annotation's content size.</returns>
  2087. virtual internal RectangleF GetContentPosition()
  2088. {
  2089. return new RectangleF(float.NaN, float.NaN, float.NaN, float.NaN);
  2090. }
  2091. /// <summary>
  2092. /// Gets an annotation's anchor point location.
  2093. /// </summary>
  2094. /// <param name="anchorX">Returns the anchor X coordinate.</param>
  2095. /// <param name="anchorY">Returns the anchor Y coordinate.</param>
  2096. /// <param name="inRelativeAnchorX">Indicates if X coordinate is in relative chart coordinates.</param>
  2097. /// <param name="inRelativeAnchorY">Indicates if Y coordinate is in relative chart coordinates.</param>
  2098. private void GetAnchorLocation(ref double anchorX, ref double anchorY, ref bool inRelativeAnchorX, ref bool inRelativeAnchorY)
  2099. {
  2100. anchorX = this.AnchorX;
  2101. anchorY = this.AnchorY;
  2102. if (this.AnchorDataPoint != null &&
  2103. this.AnchorDataPoint.series != null &&
  2104. this.Chart != null &&
  2105. this.Chart.chartPicture != null)
  2106. {
  2107. // Anchor data point is not allowed for gropped annotations
  2108. if (this.AnnotationGroup != null)
  2109. {
  2110. throw (new InvalidOperationException(SR.ExceptionAnnotationGroupedAnchorDataPointMustBeEmpty));
  2111. }
  2112. // Get data point relative coordinate
  2113. if (double.IsNaN(anchorX) || double.IsNaN(anchorY))
  2114. {
  2115. // Get X value from data point
  2116. if (double.IsNaN(anchorX))
  2117. {
  2118. anchorX = this.AnchorDataPoint.positionRel.X;
  2119. inRelativeAnchorX = true;
  2120. }
  2121. // Get Y value from data point
  2122. if (double.IsNaN(anchorY))
  2123. {
  2124. anchorY = this.AnchorDataPoint.positionRel.Y;
  2125. inRelativeAnchorY = true;
  2126. }
  2127. }
  2128. }
  2129. }
  2130. /// <summary>
  2131. /// Gets annotation object position in relative coordinates.
  2132. /// </summary>
  2133. /// <param name="location">Returns annotation location.</param>
  2134. /// <param name="size">Returns annotation size.</param>
  2135. /// <param name="anchorLocation">Returns annotation anchor point location.</param>
  2136. virtual internal void GetRelativePosition(out PointF location, out SizeF size, out PointF anchorLocation)
  2137. {
  2138. bool saveCurrentPosition = true;
  2139. //***********************************************************************
  2140. //** Check if position was precalculated
  2141. //***********************************************************************
  2142. if (!double.IsNaN(currentPositionRel.X) && !double.IsNaN(currentPositionRel.X))
  2143. {
  2144. location = currentPositionRel.Location;
  2145. size = currentPositionRel.Size;
  2146. anchorLocation = currentAnchorLocationRel;
  2147. return;
  2148. }
  2149. //***********************************************************************
  2150. //** Get vertical and horizontal axis
  2151. //***********************************************************************
  2152. Axis vertAxis = null;
  2153. Axis horizAxis = null;
  2154. GetAxes(ref vertAxis, ref horizAxis);
  2155. //***********************************************************************
  2156. //** Check if annotation was anchored to 2 points.
  2157. //***********************************************************************
  2158. if (this._anchorDataPoint != null &&
  2159. this._anchorDataPoint2 != null)
  2160. {
  2161. // Annotation size is in axis coordinates
  2162. this.IsSizeAlwaysRelative = false;
  2163. // Set annotation size
  2164. this.Height =
  2165. vertAxis.PositionToValue(this._anchorDataPoint2.positionRel.Y, false) -
  2166. vertAxis.PositionToValue(this._anchorDataPoint.positionRel.Y, false);
  2167. this.Width =
  2168. horizAxis.PositionToValue(this._anchorDataPoint2.positionRel.X, false) -
  2169. horizAxis.PositionToValue(this._anchorDataPoint.positionRel.X, false);
  2170. // Reset second anchor point after setting width and height
  2171. this._anchorDataPoint2 = null;
  2172. }
  2173. //***********************************************************************
  2174. //** Flags which indicate that coordinate was already transformed
  2175. //** into chart relative coordinate system.
  2176. //***********************************************************************
  2177. bool inRelativeX = false;
  2178. bool inRelativeY = false;
  2179. bool inRelativeWidth = (_isSizeAlwaysRelative) ? true : false;
  2180. bool inRelativeHeight = (_isSizeAlwaysRelative) ? true : false;
  2181. bool inRelativeAnchorX = false;
  2182. bool inRelativeAnchorY = false;
  2183. //***********************************************************************
  2184. //** Get anchoring coordinates from anchored Data Point.
  2185. //***********************************************************************
  2186. double anchorX = this.AnchorX;
  2187. double anchorY = this.AnchorY;
  2188. GetAnchorLocation(ref anchorX, ref anchorY, ref inRelativeAnchorX, ref inRelativeAnchorY);
  2189. //***********************************************************************
  2190. //** Calculate scaling and translation for the annotations in the group.
  2191. //***********************************************************************
  2192. AnnotationGroup group = this.AnnotationGroup;
  2193. PointF groupLocation = PointF.Empty;
  2194. double groupScaleX = 1.0;
  2195. double groupScaleY = 1.0;
  2196. if (group != null)
  2197. {
  2198. // Do not save relative position of annotations inside the group
  2199. saveCurrentPosition = false;
  2200. // Take relative position of the group
  2201. SizeF groupSize = SizeF.Empty;
  2202. PointF groupAnchorLocation = PointF.Empty;
  2203. group.GetRelativePosition(out groupLocation, out groupSize, out groupAnchorLocation);
  2204. // Calculate Scale
  2205. groupScaleX = groupSize.Width / 100.0;
  2206. groupScaleY = groupSize.Height / 100.0;
  2207. }
  2208. //***********************************************************************
  2209. //** Get annotation automatic size.
  2210. //***********************************************************************
  2211. double relativeWidth = this._width;
  2212. double relativeHeight = this._height;
  2213. // Get annotation content position
  2214. RectangleF contentPosition = GetContentPosition();
  2215. // Set annotation size if not set to custom value
  2216. if (double.IsNaN(relativeWidth))
  2217. {
  2218. relativeWidth = contentPosition.Width;
  2219. inRelativeWidth = true;
  2220. }
  2221. else
  2222. {
  2223. relativeWidth *= groupScaleX;
  2224. }
  2225. if (double.IsNaN(relativeHeight))
  2226. {
  2227. relativeHeight = contentPosition.Height;
  2228. inRelativeHeight = true;
  2229. }
  2230. else
  2231. {
  2232. relativeHeight *= groupScaleY;
  2233. }
  2234. //***********************************************************************
  2235. //** Provide "dummy" size at design time
  2236. //***********************************************************************
  2237. if (this.Chart != null && this.Chart.IsDesignMode())
  2238. {
  2239. if (this.IsSizeAlwaysRelative ||
  2240. (vertAxis == null && horizAxis == null))
  2241. {
  2242. if (double.IsNaN(relativeWidth))
  2243. {
  2244. relativeWidth = 20.0;
  2245. saveCurrentPosition = false;
  2246. }
  2247. if (double.IsNaN(relativeHeight))
  2248. {
  2249. relativeHeight = 20.0;
  2250. saveCurrentPosition = false;
  2251. }
  2252. }
  2253. }
  2254. //***********************************************************************
  2255. //** Get annotation location.
  2256. //***********************************************************************
  2257. double relativeX = this.X;
  2258. double relativeY = this.Y;
  2259. // Check if annotation location Y coordinate is defined
  2260. if (double.IsNaN(relativeY) && !double.IsNaN(anchorY))
  2261. {
  2262. inRelativeY = true;
  2263. double relativeAnchorY = anchorY;
  2264. if (!inRelativeAnchorY && vertAxis != null)
  2265. {
  2266. relativeAnchorY = vertAxis.ValueToPosition(anchorY);
  2267. }
  2268. if (this.AnchorAlignment == ContentAlignment.TopCenter ||
  2269. this.AnchorAlignment == ContentAlignment.TopLeft ||
  2270. this.AnchorAlignment == ContentAlignment.TopRight)
  2271. {
  2272. relativeY = relativeAnchorY + this.AnchorOffsetY;
  2273. relativeY *= groupScaleY;
  2274. }
  2275. else if (this.AnchorAlignment == ContentAlignment.BottomCenter ||
  2276. this.AnchorAlignment == ContentAlignment.BottomLeft ||
  2277. this.AnchorAlignment == ContentAlignment.BottomRight)
  2278. {
  2279. relativeY = relativeAnchorY - this.AnchorOffsetY;
  2280. relativeY *= groupScaleY;
  2281. if (relativeHeight != 0f && !double.IsNaN(relativeHeight))
  2282. {
  2283. if (inRelativeHeight)
  2284. {
  2285. relativeY -= relativeHeight;
  2286. }
  2287. else if (vertAxis != null)
  2288. {
  2289. float yValue = (float)vertAxis.PositionToValue(relativeY);
  2290. float bottomRel = (float)vertAxis.ValueToPosition(yValue + relativeHeight);
  2291. relativeY -= bottomRel - relativeY;
  2292. }
  2293. }
  2294. }
  2295. else
  2296. {
  2297. relativeY = relativeAnchorY + this.AnchorOffsetY;
  2298. relativeY *= groupScaleY;
  2299. if (relativeHeight != 0f && !double.IsNaN(relativeHeight))
  2300. {
  2301. if (inRelativeHeight)
  2302. {
  2303. relativeY -= relativeHeight / 2f;
  2304. }
  2305. else if (vertAxis != null)
  2306. {
  2307. float yValue = (float)vertAxis.PositionToValue(relativeY);
  2308. float bottomRel = (float)vertAxis.ValueToPosition(yValue + relativeHeight);
  2309. relativeY -= (bottomRel - relativeY) / 2f;
  2310. }
  2311. }
  2312. }
  2313. }
  2314. else
  2315. {
  2316. relativeY *= groupScaleY;
  2317. }
  2318. // Check if annotation location X coordinate is defined
  2319. if (double.IsNaN(relativeX) && !double.IsNaN(anchorX))
  2320. {
  2321. inRelativeX = true;
  2322. double relativeAnchorX = anchorX;
  2323. if (!inRelativeAnchorX && horizAxis != null)
  2324. {
  2325. relativeAnchorX = horizAxis.ValueToPosition(anchorX);
  2326. }
  2327. if (this.AnchorAlignment == ContentAlignment.BottomLeft ||
  2328. this.AnchorAlignment == ContentAlignment.MiddleLeft ||
  2329. this.AnchorAlignment == ContentAlignment.TopLeft)
  2330. {
  2331. relativeX = relativeAnchorX + this.AnchorOffsetX;
  2332. relativeX *= groupScaleX;
  2333. }
  2334. else if (this.AnchorAlignment == ContentAlignment.BottomRight ||
  2335. this.AnchorAlignment == ContentAlignment.MiddleRight ||
  2336. this.AnchorAlignment == ContentAlignment.TopRight)
  2337. {
  2338. relativeX = relativeAnchorX - this.AnchorOffsetX;
  2339. relativeX *= groupScaleX;
  2340. if (relativeWidth != 0f && !double.IsNaN(relativeWidth))
  2341. {
  2342. if (inRelativeWidth)
  2343. {
  2344. relativeX -= relativeWidth;
  2345. }
  2346. else if (horizAxis != null)
  2347. {
  2348. float xValue = (float)horizAxis.PositionToValue(relativeX);
  2349. relativeX -= horizAxis.ValueToPosition(xValue + relativeWidth) - relativeX;
  2350. }
  2351. }
  2352. }
  2353. else
  2354. {
  2355. relativeX = relativeAnchorX + this.AnchorOffsetX;
  2356. relativeX *= groupScaleX;
  2357. if (relativeWidth != 0f && !double.IsNaN(relativeWidth))
  2358. {
  2359. if (inRelativeWidth)
  2360. {
  2361. relativeX -= relativeWidth / 2f;
  2362. }
  2363. else if (horizAxis != null)
  2364. {
  2365. float xValue = (float)horizAxis.PositionToValue(relativeX);
  2366. relativeX -= (horizAxis.ValueToPosition(xValue + relativeWidth) - relativeX) / 2f;
  2367. }
  2368. }
  2369. }
  2370. }
  2371. else
  2372. {
  2373. relativeX *= groupScaleX;
  2374. }
  2375. // Translate
  2376. relativeX += groupLocation.X;
  2377. relativeY += groupLocation.Y;
  2378. //***********************************************************************
  2379. //** Get annotation automatic location.
  2380. //***********************************************************************
  2381. // Set annotation size if not set to custom value
  2382. if (double.IsNaN(relativeX))
  2383. {
  2384. relativeX = contentPosition.X * groupScaleX;
  2385. inRelativeX = true;
  2386. }
  2387. if (double.IsNaN(relativeY))
  2388. {
  2389. relativeY = contentPosition.Y * groupScaleY;
  2390. inRelativeY = true;
  2391. }
  2392. //***********************************************************************
  2393. //** Convert coordinates from axes values to relative coordinates.
  2394. //***********************************************************************
  2395. // Check if values are set in axis values
  2396. if (horizAxis != null)
  2397. {
  2398. if (!inRelativeX)
  2399. {
  2400. relativeX = horizAxis.ValueToPosition(relativeX);
  2401. }
  2402. if (!inRelativeAnchorX)
  2403. {
  2404. anchorX = horizAxis.ValueToPosition(anchorX);
  2405. }
  2406. if (!inRelativeWidth)
  2407. {
  2408. relativeWidth = horizAxis.ValueToPosition(
  2409. horizAxis.PositionToValue(relativeX, false) + relativeWidth) - relativeX;
  2410. }
  2411. }
  2412. if (vertAxis != null)
  2413. {
  2414. if (!inRelativeY)
  2415. {
  2416. relativeY = vertAxis.ValueToPosition(relativeY);
  2417. }
  2418. if (!inRelativeAnchorY)
  2419. {
  2420. anchorY = vertAxis.ValueToPosition(anchorY);
  2421. }
  2422. if (!inRelativeHeight)
  2423. {
  2424. relativeHeight = vertAxis.ValueToPosition(
  2425. vertAxis.PositionToValue(relativeY, false) + relativeHeight) - relativeY;
  2426. }
  2427. }
  2428. bool isTextAnnotation = this is TextAnnotation;
  2429. //***********************************************************************
  2430. //** Apply 3D transforamtion if required
  2431. //***********************************************************************
  2432. ChartArea chartArea = null;
  2433. if (horizAxis != null && horizAxis.ChartArea != null)
  2434. {
  2435. chartArea = horizAxis.ChartArea;
  2436. }
  2437. if (vertAxis != null && vertAxis.ChartArea != null)
  2438. {
  2439. chartArea = vertAxis.ChartArea;
  2440. }
  2441. if (chartArea != null &&
  2442. chartArea.Area3DStyle.Enable3D == true &&
  2443. !chartArea.chartAreaIsCurcular &&
  2444. chartArea.requireAxes &&
  2445. chartArea.matrix3D.IsInitialized())
  2446. {
  2447. // Get anotation Z coordinate (use scene depth or anchored point Z position)
  2448. float positionZ = chartArea.areaSceneDepth;
  2449. if (this.AnchorDataPoint != null && this.AnchorDataPoint.series != null)
  2450. {
  2451. float depth = 0f;
  2452. chartArea.GetSeriesZPositionAndDepth(
  2453. this.AnchorDataPoint.series,
  2454. out depth,
  2455. out positionZ);
  2456. positionZ += depth / 2f;
  2457. }
  2458. // Define 3D points of annotation object
  2459. Point3D[] annot3DPoints = new Point3D[3];
  2460. annot3DPoints[0] = new Point3D((float)relativeX, (float)relativeY, positionZ);
  2461. annot3DPoints[1] = new Point3D((float)(relativeX + relativeWidth), (float)(relativeY + relativeHeight), positionZ);
  2462. annot3DPoints[2] = new Point3D((float)anchorX, (float)anchorY, positionZ);
  2463. // Tranform cube coordinates
  2464. chartArea.matrix3D.TransformPoints(annot3DPoints);
  2465. // Get transformed coordinates
  2466. relativeX = annot3DPoints[0].X;
  2467. relativeY = annot3DPoints[0].Y;
  2468. anchorX = annot3DPoints[2].X;
  2469. anchorY = annot3DPoints[2].Y;
  2470. // Don't adjust size for text annotation
  2471. if (!(isTextAnnotation && this.IsSizeAlwaysRelative))
  2472. {
  2473. relativeWidth = annot3DPoints[1].X - relativeX;
  2474. relativeHeight = annot3DPoints[1].Y - relativeY;
  2475. }
  2476. }
  2477. //***********************************************************************
  2478. //** Provide "dummy" position at design time
  2479. //***********************************************************************
  2480. if (this.Chart != null && this.Chart.IsDesignMode())
  2481. {
  2482. if (double.IsNaN(relativeX))
  2483. {
  2484. relativeX = groupLocation.X;
  2485. saveCurrentPosition = false;
  2486. }
  2487. if (double.IsNaN(relativeY))
  2488. {
  2489. relativeY = groupLocation.Y;
  2490. saveCurrentPosition = false;
  2491. }
  2492. if (double.IsNaN(relativeWidth))
  2493. {
  2494. relativeWidth = 20.0 * groupScaleX;
  2495. saveCurrentPosition = false;
  2496. }
  2497. if (double.IsNaN(relativeHeight))
  2498. {
  2499. relativeHeight = 20.0 * groupScaleY;
  2500. saveCurrentPosition = false;
  2501. }
  2502. }
  2503. //***********************************************************************
  2504. //** Initialize returned values
  2505. //***********************************************************************
  2506. location = new PointF((float)relativeX, (float)relativeY);
  2507. size = new SizeF((float)relativeWidth, (float)relativeHeight);
  2508. anchorLocation = new PointF((float)anchorX, (float)anchorY);
  2509. //***********************************************************************
  2510. //** Adjust text based annotaion position using SmartLabelStyle.
  2511. //***********************************************************************
  2512. // Check if smart labels are enabled
  2513. if (this.SmartLabelStyle.Enabled && isTextAnnotation &&
  2514. group == null)
  2515. {
  2516. // Anchor point must be set
  2517. if (!double.IsNaN(anchorX) && !double.IsNaN(anchorY) &&
  2518. double.IsNaN(this.X) && double.IsNaN(this.Y))
  2519. {
  2520. if (this.Chart != null &&
  2521. this.Chart.chartPicture != null)
  2522. {
  2523. // Remember old movement distance restriction
  2524. double oldMinMovingDistance = this.SmartLabelStyle.MinMovingDistance;
  2525. double oldMaxMovingDistance = this.SmartLabelStyle.MaxMovingDistance;
  2526. // Increase annotation moving restrictions according to the anchor offset
  2527. PointF anchorOffsetAbs = this.GetGraphics().GetAbsolutePoint(
  2528. new PointF((float)this.AnchorOffsetX, (float)this.AnchorOffsetY));
  2529. float maxAnchorOffsetAbs = Math.Max(anchorOffsetAbs.X, anchorOffsetAbs.Y);
  2530. if (maxAnchorOffsetAbs > 0.0)
  2531. {
  2532. this.SmartLabelStyle.MinMovingDistance += maxAnchorOffsetAbs;
  2533. this.SmartLabelStyle.MaxMovingDistance += maxAnchorOffsetAbs;
  2534. }
  2535. // Adjust label position using SmartLabelStyle algorithm
  2536. LabelAlignmentStyles labelAlignment = LabelAlignmentStyles.Bottom;
  2537. using (StringFormat format = new StringFormat())
  2538. {
  2539. SizeF markerSizeRel = new SizeF((float)this.AnchorOffsetX, (float)this.AnchorOffsetY);
  2540. PointF newlocation = this.Chart.chartPicture.annotationSmartLabel.AdjustSmartLabelPosition(
  2541. this.Common,
  2542. this.Chart.chartPicture.ChartGraph,
  2543. chartArea,
  2544. this.SmartLabelStyle,
  2545. location,
  2546. size,
  2547. format,
  2548. anchorLocation,
  2549. markerSizeRel,
  2550. labelAlignment,
  2551. (this is CalloutAnnotation));
  2552. // Restore old movement distance restriction
  2553. this.SmartLabelStyle.MinMovingDistance = oldMinMovingDistance;
  2554. this.SmartLabelStyle.MaxMovingDistance = oldMaxMovingDistance;
  2555. // Check if annotation should be hidden
  2556. if (newlocation.IsEmpty)
  2557. {
  2558. location = new PointF(float.NaN, float.NaN);
  2559. }
  2560. else
  2561. {
  2562. // Get new position using alignment in format
  2563. RectangleF newPosition = this.Chart.chartPicture.annotationSmartLabel.GetLabelPosition(
  2564. this.Chart.chartPicture.ChartGraph,
  2565. newlocation,
  2566. size,
  2567. format,
  2568. false);
  2569. // Set new location
  2570. location = newPosition.Location;
  2571. }
  2572. }
  2573. }
  2574. }
  2575. else
  2576. {
  2577. // Add annotation position into the list (to prevent overlapping)
  2578. using (StringFormat format = new StringFormat())
  2579. {
  2580. this.Chart.chartPicture.annotationSmartLabel.AddSmartLabelPosition(
  2581. this.Chart.chartPicture.ChartGraph,
  2582. location,
  2583. size,
  2584. format);
  2585. }
  2586. }
  2587. }
  2588. //***********************************************************************
  2589. //** Save calculated position
  2590. //***********************************************************************
  2591. if (saveCurrentPosition)
  2592. {
  2593. currentPositionRel = new RectangleF(location, size);
  2594. currentAnchorLocationRel = new PointF(anchorLocation.X, anchorLocation.Y);
  2595. }
  2596. }
  2597. /// <summary>
  2598. /// Set annotation object position using rectangle in relative coordinates.
  2599. /// Automatically converts relative coordinates to axes values if required.
  2600. /// </summary>
  2601. /// <param name="position">Position in relative coordinates.</param>
  2602. /// <param name="anchorPoint">Anchor location in relative coordinates.</param>
  2603. internal void SetPositionRelative(RectangleF position, PointF anchorPoint)
  2604. {
  2605. SetPositionRelative(position, anchorPoint, false);
  2606. }
  2607. /// <summary>
  2608. /// Set annotation object position using rectangle in relative coordinates.
  2609. /// Automatically converts relative coordinates to axes values if required.
  2610. /// </summary>
  2611. /// <param name="position">Position in relative coordinates.</param>
  2612. /// <param name="anchorPoint">Anchor location in relative coordinates.</param>
  2613. /// <param name="userInput">Indicates if position changing was a result of the user input.</param>
  2614. internal void SetPositionRelative(RectangleF position, PointF anchorPoint, bool userInput)
  2615. {
  2616. double newX = position.X;
  2617. double newY = position.Y;
  2618. double newRight = position.Right;
  2619. double newBottom = position.Bottom;
  2620. double newWidth = position.Width;
  2621. double newHeight = position.Height;
  2622. double newAnchorX = anchorPoint.X;
  2623. double newAnchorY = anchorPoint.Y;
  2624. //***********************************************************************
  2625. //** Set pre calculated position and anchor location
  2626. //***********************************************************************
  2627. this.currentPositionRel = new RectangleF(position.Location, position.Size);
  2628. this.currentAnchorLocationRel = new PointF(anchorPoint.X, anchorPoint.Y);
  2629. //***********************************************************************
  2630. //** Get vertical and horizontal axis
  2631. //***********************************************************************
  2632. Axis vertAxis = null;
  2633. Axis horizAxis = null;
  2634. GetAxes(ref vertAxis, ref horizAxis);
  2635. //***********************************************************************
  2636. //** Disable anchoring to point and axes in 3D
  2637. //** This is done due to the issues of moving elements in 3D space.
  2638. //***********************************************************************
  2639. ChartArea chartArea = null;
  2640. if (horizAxis != null && horizAxis.ChartArea != null)
  2641. {
  2642. chartArea = horizAxis.ChartArea;
  2643. }
  2644. if (vertAxis != null && vertAxis.ChartArea != null)
  2645. {
  2646. chartArea = vertAxis.ChartArea;
  2647. }
  2648. if (chartArea != null && chartArea.Area3DStyle.Enable3D == true)
  2649. {
  2650. // If anchor point was set - get its relative position and use it as an anchor point
  2651. if (this.AnchorDataPoint != null)
  2652. {
  2653. bool inRelativeCoordX = true;
  2654. bool inRelativeCoordY = true;
  2655. this.GetAnchorLocation(ref newAnchorX, ref newAnchorY, ref inRelativeCoordX, ref inRelativeCoordY);
  2656. this.currentAnchorLocationRel = new PointF((float)newAnchorX, (float)newAnchorY);
  2657. }
  2658. // In 3D always use relative annotation coordinates
  2659. // Disconnect annotation from axes and anchor point
  2660. this.AnchorDataPoint = null;
  2661. this.AxisX = null;
  2662. this.AxisY = null;
  2663. horizAxis = null;
  2664. vertAxis = null;
  2665. }
  2666. //***********************************************************************
  2667. //** Convert relative coordinates to axis values
  2668. //***********************************************************************
  2669. if (horizAxis != null)
  2670. {
  2671. newX = horizAxis.PositionToValue(newX, false);
  2672. if (!double.IsNaN(newAnchorX))
  2673. {
  2674. newAnchorX = horizAxis.PositionToValue(newAnchorX, false);
  2675. }
  2676. // Adjust for the IsLogarithmic axis
  2677. if (horizAxis.IsLogarithmic)
  2678. {
  2679. newX = Math.Pow(horizAxis.logarithmBase, newX);
  2680. if (!double.IsNaN(newAnchorX))
  2681. {
  2682. newAnchorX = Math.Pow(horizAxis.logarithmBase, newAnchorX);
  2683. }
  2684. }
  2685. if (!this.IsSizeAlwaysRelative)
  2686. {
  2687. if (float.IsNaN(position.Right) &&
  2688. !float.IsNaN(position.Width) &&
  2689. !float.IsNaN(anchorPoint.X))
  2690. {
  2691. newRight = horizAxis.PositionToValue(anchorPoint.X + position.Width, false);
  2692. if (horizAxis.IsLogarithmic)
  2693. {
  2694. newRight = Math.Pow(horizAxis.logarithmBase, newRight);
  2695. }
  2696. newWidth = newRight - newAnchorX;
  2697. }
  2698. else
  2699. {
  2700. newRight = horizAxis.PositionToValue(position.Right, false);
  2701. if (horizAxis.IsLogarithmic)
  2702. {
  2703. newRight = Math.Pow(horizAxis.logarithmBase, newRight);
  2704. }
  2705. newWidth = newRight - newX;
  2706. }
  2707. }
  2708. }
  2709. if (vertAxis != null)
  2710. {
  2711. newY = vertAxis.PositionToValue(newY, false);
  2712. if (!double.IsNaN(newAnchorY))
  2713. {
  2714. newAnchorY = vertAxis.PositionToValue(newAnchorY, false);
  2715. }
  2716. // NOTE: Fixes issue #4113
  2717. // Adjust for the IsLogarithmic axis
  2718. if (vertAxis.IsLogarithmic)
  2719. {
  2720. newY = Math.Pow(vertAxis.logarithmBase, newY);
  2721. if (!double.IsNaN(newAnchorY))
  2722. {
  2723. newAnchorY = Math.Pow(vertAxis.logarithmBase, newAnchorY);
  2724. }
  2725. }
  2726. if (!this.IsSizeAlwaysRelative)
  2727. {
  2728. if (float.IsNaN(position.Bottom) &&
  2729. !float.IsNaN(position.Height) &&
  2730. !float.IsNaN(anchorPoint.Y))
  2731. {
  2732. newBottom = vertAxis.PositionToValue(anchorPoint.Y + position.Height, false);
  2733. if (vertAxis.IsLogarithmic)
  2734. {
  2735. newBottom = Math.Pow(vertAxis.logarithmBase, newBottom);
  2736. }
  2737. newHeight = newBottom - newAnchorY;
  2738. }
  2739. else
  2740. {
  2741. newBottom = vertAxis.PositionToValue(position.Bottom, false);
  2742. if (vertAxis.IsLogarithmic)
  2743. {
  2744. newBottom = Math.Pow(vertAxis.logarithmBase, newBottom);
  2745. }
  2746. newHeight = newBottom - newY;
  2747. }
  2748. }
  2749. }
  2750. // Fire position changing event when position changed by user.
  2751. if (userInput)
  2752. {
  2753. // Set flag that annotation position was changed
  2754. this.positionChanged = true;
  2755. // Fire position changing event
  2756. if (this.Chart != null)
  2757. {
  2758. AnnotationPositionChangingEventArgs args = new AnnotationPositionChangingEventArgs();
  2759. args.NewLocationX = newX;
  2760. args.NewLocationY = newY;
  2761. args.NewSizeWidth = newWidth;
  2762. args.NewSizeHeight = newHeight;
  2763. args.NewAnchorLocationX = newAnchorX;
  2764. args.NewAnchorLocationY = newAnchorY;
  2765. args.Annotation = this;
  2766. if (this.Chart.OnAnnotationPositionChanging(ref args))
  2767. {
  2768. // Get user changed position/anchor
  2769. newX = args.NewLocationX;
  2770. newY = args.NewLocationY;
  2771. newWidth = args.NewSizeWidth;
  2772. newHeight = args.NewSizeHeight;
  2773. newAnchorX = args.NewAnchorLocationX;
  2774. newAnchorY = args.NewAnchorLocationY;
  2775. }
  2776. }
  2777. }
  2778. // Adjust location & size
  2779. this.X = newX;
  2780. this.Y = newY;
  2781. this.Width = newWidth;
  2782. this.Height = newHeight;
  2783. this.AnchorX = newAnchorX;
  2784. this.AnchorY = newAnchorY;
  2785. // Invalidate annotation
  2786. this.Invalidate();
  2787. return;
  2788. }
  2789. /// <summary>
  2790. /// Adjust annotation location and\or size as a result of user action.
  2791. /// </summary>
  2792. /// <param name="movingDistance">Distance to resize/move the annotation.</param>
  2793. /// <param name="resizeMode">Resizing mode.</param>
  2794. virtual internal void AdjustLocationSize(SizeF movingDistance, ResizingMode resizeMode)
  2795. {
  2796. AdjustLocationSize(movingDistance, resizeMode, true);
  2797. }
  2798. /// <summary>
  2799. /// Adjust annotation location and\or size as a result of user action.
  2800. /// </summary>
  2801. /// <param name="movingDistance">Distance to resize/move the annotation.</param>
  2802. /// <param name="resizeMode">Resizing mode.</param>
  2803. /// <param name="pixelCoord">Distance is in pixels, otherwise relative.</param>
  2804. virtual internal void AdjustLocationSize(SizeF movingDistance, ResizingMode resizeMode, bool pixelCoord)
  2805. {
  2806. AdjustLocationSize(movingDistance, resizeMode, pixelCoord, false);
  2807. }
  2808. /// <summary>
  2809. /// Adjust annotation location and\or size as a result of user action.
  2810. /// </summary>
  2811. /// <param name="movingDistance">Distance to resize/move the annotation.</param>
  2812. /// <param name="resizeMode">Resizing mode.</param>
  2813. /// <param name="pixelCoord">Distance is in pixels, otherwise relative.</param>
  2814. /// <param name="userInput">Indicates if position changing was a result of the user input.</param>
  2815. virtual internal void AdjustLocationSize(SizeF movingDistance, ResizingMode resizeMode, bool pixelCoord, bool userInput)
  2816. {
  2817. if (!movingDistance.IsEmpty)
  2818. {
  2819. // Convert pixel coordinates into relative
  2820. if (pixelCoord)
  2821. {
  2822. movingDistance = Chart.chartPicture.ChartGraph.GetRelativeSize(movingDistance);
  2823. }
  2824. // Get annotation position in relative coordinates
  2825. PointF firstPoint = PointF.Empty;
  2826. PointF anchorPoint = PointF.Empty;
  2827. SizeF size = SizeF.Empty;
  2828. if (userInput)
  2829. {
  2830. if (this.startMovePositionRel.X == 0f &&
  2831. this.startMovePositionRel.Y == 0f &&
  2832. this.startMovePositionRel.Width == 0f &&
  2833. this.startMovePositionRel.Height == 0f)
  2834. {
  2835. GetRelativePosition(out firstPoint, out size, out anchorPoint);
  2836. this.startMovePositionRel = new RectangleF(firstPoint, size);
  2837. this.startMoveAnchorLocationRel = new PointF(anchorPoint.X, anchorPoint.Y);
  2838. }
  2839. firstPoint = this.startMovePositionRel.Location;
  2840. size = this.startMovePositionRel.Size;
  2841. anchorPoint = this.startMoveAnchorLocationRel;
  2842. }
  2843. else
  2844. {
  2845. GetRelativePosition(out firstPoint, out size, out anchorPoint);
  2846. }
  2847. if (resizeMode == ResizingMode.TopLeftHandle)
  2848. {
  2849. firstPoint.X -= movingDistance.Width;
  2850. firstPoint.Y -= movingDistance.Height;
  2851. size.Width += movingDistance.Width;
  2852. size.Height += movingDistance.Height;
  2853. }
  2854. else if (resizeMode == ResizingMode.TopHandle)
  2855. {
  2856. firstPoint.Y -= movingDistance.Height;
  2857. size.Height += movingDistance.Height;
  2858. }
  2859. else if (resizeMode == ResizingMode.TopRightHandle)
  2860. {
  2861. firstPoint.Y -= movingDistance.Height;
  2862. size.Width -= movingDistance.Width;
  2863. size.Height += movingDistance.Height;
  2864. }
  2865. else if (resizeMode == ResizingMode.RightHandle)
  2866. {
  2867. size.Width -= movingDistance.Width;
  2868. }
  2869. else if (resizeMode == ResizingMode.BottomRightHandle)
  2870. {
  2871. size.Width -= movingDistance.Width;
  2872. size.Height -= movingDistance.Height;
  2873. }
  2874. else if (resizeMode == ResizingMode.BottomHandle)
  2875. {
  2876. size.Height -= movingDistance.Height;
  2877. }
  2878. else if (resizeMode == ResizingMode.BottomLeftHandle)
  2879. {
  2880. firstPoint.X -= movingDistance.Width;
  2881. size.Width += movingDistance.Width;
  2882. size.Height -= movingDistance.Height;
  2883. }
  2884. else if (resizeMode == ResizingMode.LeftHandle)
  2885. {
  2886. firstPoint.X -= movingDistance.Width;
  2887. size.Width += movingDistance.Width;
  2888. }
  2889. else if (resizeMode == ResizingMode.AnchorHandle)
  2890. {
  2891. anchorPoint.X -= movingDistance.Width;
  2892. anchorPoint.Y -= movingDistance.Height;
  2893. }
  2894. else if (resizeMode == ResizingMode.Moving)
  2895. {
  2896. firstPoint.X -= movingDistance.Width;
  2897. firstPoint.Y -= movingDistance.Height;
  2898. }
  2899. // Make sure we do not override automatic Width and Heigth
  2900. if (resizeMode == ResizingMode.Moving)
  2901. {
  2902. if (double.IsNaN(this.Width))
  2903. {
  2904. size.Width = float.NaN;
  2905. }
  2906. if (double.IsNaN(this.Height))
  2907. {
  2908. size.Height = float.NaN;
  2909. }
  2910. }
  2911. // Make sure we do not override automatic X and Y
  2912. if (resizeMode == ResizingMode.AnchorHandle)
  2913. {
  2914. if (double.IsNaN(this.X))
  2915. {
  2916. firstPoint.X = float.NaN;
  2917. }
  2918. if (double.IsNaN(this.Y))
  2919. {
  2920. firstPoint.Y = float.NaN;
  2921. }
  2922. }
  2923. else if (double.IsNaN(this.AnchorX) || double.IsNaN(this.AnchorY))
  2924. {
  2925. anchorPoint = new PointF(float.NaN, float.NaN);
  2926. }
  2927. // Set annotation position from rectangle in relative coordinates
  2928. SetPositionRelative(new RectangleF(firstPoint, size), anchorPoint, userInput);
  2929. }
  2930. return;
  2931. }
  2932. #endregion
  2933. #region Anchor Point and Axes Converters
  2934. /// <summary>
  2935. /// Checks if annotation draw anything in the anchor position (except selection handle)
  2936. /// </summary>
  2937. /// <returns>True if annotation "connects" itself and anchor point visually.</returns>
  2938. virtual internal bool IsAnchorDrawn()
  2939. {
  2940. return false;
  2941. }
  2942. /// <summary>
  2943. /// Gets data point by name.
  2944. /// </summary>
  2945. /// <param name="dataPointName">Data point name to find.</param>
  2946. /// <returns>Data point.</returns>
  2947. internal DataPoint GetDataPointByName(string dataPointName)
  2948. {
  2949. DataPoint dataPoint = null;
  2950. if (Chart != null && dataPointName.Length > 0)
  2951. {
  2952. // Split series name and point index
  2953. int separatorIndex = dataPointName.IndexOf("\\r", StringComparison.Ordinal);
  2954. if (separatorIndex > 0)
  2955. {
  2956. string seriesName = dataPointName.Substring(0, separatorIndex);
  2957. string pointIndex = dataPointName.Substring(separatorIndex + 2);
  2958. int index = 0;
  2959. if (int.TryParse(pointIndex, NumberStyles.Any, CultureInfo.InvariantCulture, out index))
  2960. {
  2961. dataPoint = Chart.Series[seriesName].Points[index];
  2962. }
  2963. }
  2964. }
  2965. return dataPoint;
  2966. }
  2967. /// <summary>
  2968. /// Gets axis by name.
  2969. /// </summary>
  2970. /// <param name="axisName">Axis name to find.</param>
  2971. /// <returns>Data point.</returns>
  2972. private Axis GetAxisByName(string axisName)
  2973. {
  2974. Debug.Assert(axisName != null, "GetAxisByName: handed a null axis name");
  2975. Axis axis = null;
  2976. try
  2977. {
  2978. if (Chart != null && axisName.Length > 0)
  2979. {
  2980. // Split series name and point index
  2981. int separatorIndex = axisName.IndexOf("\\r", StringComparison.Ordinal);
  2982. if (separatorIndex > 0)
  2983. {
  2984. string areaName = axisName.Substring(0, separatorIndex);
  2985. string axisType = axisName.Substring(separatorIndex + 2);
  2986. switch ((AxisName)Enum.Parse(typeof(AxisName), axisType))
  2987. {
  2988. case (AxisName.X):
  2989. axis = Chart.ChartAreas[areaName].AxisX;
  2990. break;
  2991. case (AxisName.Y):
  2992. axis = Chart.ChartAreas[areaName].AxisY;
  2993. break;
  2994. case (AxisName.X2):
  2995. axis = Chart.ChartAreas[areaName].AxisX2;
  2996. break;
  2997. case (AxisName.Y2):
  2998. axis = Chart.ChartAreas[areaName].AxisY2;
  2999. break;
  3000. }
  3001. }
  3002. }
  3003. }
  3004. catch (ArgumentNullException)
  3005. {
  3006. axis = null;
  3007. }
  3008. catch (ArgumentException)
  3009. {
  3010. axis = null;
  3011. }
  3012. return axis;
  3013. }
  3014. /// <summary>
  3015. /// Gets data point unique name.
  3016. /// </summary>
  3017. /// <param name="dataPoint">Data point to get the name for.</param>
  3018. /// <returns>Data point name.</returns>
  3019. internal string GetDataPointName(DataPoint dataPoint)
  3020. {
  3021. string name = String.Empty;
  3022. if (dataPoint.series != null)
  3023. {
  3024. int pointIndex = dataPoint.series.Points.IndexOf(dataPoint);
  3025. if (pointIndex >= 0)
  3026. {
  3027. name = dataPoint.series.Name +
  3028. "\\r" +
  3029. pointIndex.ToString(CultureInfo.InvariantCulture);
  3030. }
  3031. }
  3032. return name;
  3033. }
  3034. /// <summary>
  3035. /// Gets axis unique name.
  3036. /// </summary>
  3037. /// <param name="axis">Axis to get the name for.</param>
  3038. /// <returns>Axis name.</returns>
  3039. private string GetAxisName(Axis axis)
  3040. {
  3041. string name = String.Empty;
  3042. if (axis.ChartArea != null)
  3043. {
  3044. name = axis.ChartArea.Name +
  3045. "\\r" +
  3046. axis.AxisName.ToString();
  3047. }
  3048. return name;
  3049. }
  3050. #endregion
  3051. #region Z Order Methods
  3052. /// <summary>
  3053. /// Sends an annotation to the back of all annotations.
  3054. /// <seealso cref="BringToFront"/>
  3055. /// </summary>
  3056. virtual public void SendToBack()
  3057. {
  3058. // Find collection of annotation objects this annotation belongs too
  3059. AnnotationCollection collection = null;
  3060. if (Chart != null)
  3061. {
  3062. collection = Chart.Annotations;
  3063. }
  3064. // Check if annotation belongs to the group
  3065. AnnotationGroup group = AnnotationGroup;
  3066. if (group != null)
  3067. {
  3068. collection = group.Annotations;
  3069. }
  3070. // Check if annotation is found
  3071. if (collection != null)
  3072. {
  3073. Annotation annot = collection.FindByName(this.Name);
  3074. if (annot != null)
  3075. {
  3076. // Reinsert annotation at the beginning of the collection
  3077. collection.Remove(annot);
  3078. collection.Insert(0, annot);
  3079. }
  3080. }
  3081. }
  3082. /// <summary>
  3083. /// Brings an annotation to the front of all annotations.
  3084. /// <seealso cref="SendToBack"/>
  3085. /// </summary>
  3086. virtual public void BringToFront()
  3087. {
  3088. // Find collection of annotation objects this annotation belongs too
  3089. AnnotationCollection collection = null;
  3090. if (Chart != null)
  3091. {
  3092. collection = Chart.Annotations;
  3093. }
  3094. // Check if annotation belongs to the group
  3095. AnnotationGroup group = AnnotationGroup;
  3096. if (group != null)
  3097. {
  3098. collection = group.Annotations;
  3099. }
  3100. // Check if annotation is found
  3101. if (collection != null)
  3102. {
  3103. Annotation annot = collection.FindByName(this.Name);
  3104. if (annot != null)
  3105. {
  3106. // Reinsert annotation at the end of the collection
  3107. collection.Remove(annot);
  3108. collection.Add(this);
  3109. }
  3110. }
  3111. }
  3112. #endregion // Z Order Methods
  3113. #region Group Related Methods
  3114. #endregion // Group Related Methods
  3115. #region SmartLabelStyle methods
  3116. /// <summary>
  3117. /// Adds anchor position to the list. Used to check SmartLabelStyle overlapping.
  3118. /// </summary>
  3119. /// <param name="list">List to add to.</param>
  3120. internal void AddSmartLabelMarkerPositions(ArrayList list)
  3121. {
  3122. // Anchor position is added to the list of non-overlapped markers
  3123. if (this.Visible && this.IsAnchorDrawn())
  3124. {
  3125. // Get vertical and horizontal axis
  3126. Axis vertAxis = null;
  3127. Axis horizAxis = null;
  3128. GetAxes(ref vertAxis, ref horizAxis);
  3129. // Get anchor position
  3130. double anchorX = double.NaN;
  3131. double anchorY = double.NaN;
  3132. bool relativeX = false;
  3133. bool relativeY = false;
  3134. this.GetAnchorLocation(ref anchorX, ref anchorY, ref relativeX, ref relativeY);
  3135. // Convert anchor location to relative coordinates
  3136. if (!double.IsNaN(anchorX) && !double.IsNaN(anchorY))
  3137. {
  3138. if (!relativeX && horizAxis != null)
  3139. {
  3140. anchorX = horizAxis.ValueToPosition(anchorX);
  3141. }
  3142. if (!relativeY && vertAxis != null)
  3143. {
  3144. anchorY = vertAxis.ValueToPosition(anchorY);
  3145. }
  3146. // Apply 3D transforamtion if required
  3147. ChartArea chartArea = null;
  3148. if (horizAxis != null && horizAxis.ChartArea != null)
  3149. {
  3150. chartArea = horizAxis.ChartArea;
  3151. }
  3152. if (vertAxis != null && vertAxis.ChartArea != null)
  3153. {
  3154. chartArea = vertAxis.ChartArea;
  3155. }
  3156. if (chartArea != null &&
  3157. chartArea.Area3DStyle.Enable3D == true &&
  3158. !chartArea.chartAreaIsCurcular &&
  3159. chartArea.requireAxes &&
  3160. chartArea.matrix3D.IsInitialized())
  3161. {
  3162. // Get anotation Z coordinate (use scene depth or anchored point Z position)
  3163. float positionZ = chartArea.areaSceneDepth;
  3164. if (this.AnchorDataPoint != null && this.AnchorDataPoint.series != null)
  3165. {
  3166. float depth = 0f;
  3167. chartArea.GetSeriesZPositionAndDepth(
  3168. this.AnchorDataPoint.series,
  3169. out depth,
  3170. out positionZ);
  3171. positionZ += depth / 2f;
  3172. }
  3173. // Define 3D points of annotation object
  3174. Point3D[] annot3DPoints = new Point3D[1];
  3175. annot3DPoints[0] = new Point3D((float)anchorX, (float)anchorY, positionZ);
  3176. // Tranform cube coordinates
  3177. chartArea.matrix3D.TransformPoints(annot3DPoints);
  3178. // Get transformed coordinates
  3179. anchorX = annot3DPoints[0].X;
  3180. anchorY = annot3DPoints[0].Y;
  3181. }
  3182. // Save selection handles position in array elements 0 and 4
  3183. if (this.GetGraphics() != null)
  3184. {
  3185. SizeF markerSizeRel = this.GetGraphics().GetRelativeSize(
  3186. new SizeF(1f, 1f));
  3187. RectangleF anchorRect = new RectangleF(
  3188. (float)anchorX - markerSizeRel.Width / 2f,
  3189. (float)anchorY - markerSizeRel.Height / 2f,
  3190. markerSizeRel.Width,
  3191. markerSizeRel.Height);
  3192. list.Add(anchorRect);
  3193. }
  3194. }
  3195. }
  3196. }
  3197. #endregion
  3198. #region Public Anchoring Methods
  3199. /// <summary>
  3200. /// Anchors an annotation to a data point.
  3201. /// <seealso cref="AnchorDataPoint"/>
  3202. /// <seealso cref="AnchorX"/>
  3203. /// <seealso cref="AnchorY"/>
  3204. /// </summary>
  3205. /// <param name="dataPoint">
  3206. /// <see cref="DataPoint"/> to be anchored to.
  3207. /// </param>
  3208. /// <remarks>
  3209. /// Anchors an annotation to the specified data point.
  3210. /// </remarks>
  3211. public void SetAnchor(DataPoint dataPoint)
  3212. {
  3213. SetAnchor(dataPoint, null);
  3214. }
  3215. /// <summary>
  3216. /// Anchors an annotation to two data points.
  3217. /// <seealso cref="AnchorDataPoint"/>
  3218. /// <seealso cref="AnchorX"/>
  3219. /// <seealso cref="AnchorY"/>
  3220. /// </summary>
  3221. /// <param name="dataPoint1">
  3222. /// First anchor <see cref="DataPoint"/>.
  3223. /// </param>
  3224. /// <param name="dataPoint2">
  3225. /// Second anchor <see cref="DataPoint"/>.
  3226. /// </param>
  3227. /// <remarks>
  3228. /// Anchors an annotation's top/left and bottom/right corners to the
  3229. /// specified data points.
  3230. /// </remarks>
  3231. public void SetAnchor(DataPoint dataPoint1, DataPoint dataPoint2)
  3232. {
  3233. // Set annotation position to automatic
  3234. this.X = double.NaN;
  3235. this.Y = double.NaN;
  3236. // Reset anchor point if any
  3237. this.AnchorX = double.NaN;
  3238. this.AnchorY = double.NaN;
  3239. // Set anchor point
  3240. this.AnchorDataPoint = dataPoint1;
  3241. // Get vertical and horizontal axis
  3242. Axis vertAxis = null;
  3243. Axis horizAxis = null;
  3244. GetAxes(ref vertAxis, ref horizAxis);
  3245. // Set Width and Height in axis coordinates
  3246. if (dataPoint2 != null && dataPoint1 != null)
  3247. {
  3248. this._anchorDataPoint2 = dataPoint2;
  3249. }
  3250. // Invalidate annotation
  3251. this.Invalidate();
  3252. }
  3253. #endregion // Public Anchoring Methods
  3254. #region Placement Methods
  3255. /// <summary>
  3256. /// Begins end user placement of an annotation using the mouse.
  3257. /// </summary>
  3258. /// <remarks>
  3259. /// When this method is called, the end user is allowed to place an annotation using the
  3260. /// mouse.
  3261. /// <para>
  3262. /// Placement will finish when the end user specifies all required points, or
  3263. /// the <see cref="EndPlacement"/> method is called.</para>
  3264. /// </remarks>
  3265. virtual public void BeginPlacement()
  3266. {
  3267. // Can't place annotations inside the group
  3268. if (this.AnnotationGroup != null)
  3269. {
  3270. throw (new InvalidOperationException(SR.ExceptionAnnotationGroupedUnableToStartPlacement));
  3271. }
  3272. if (this.Chart != null)
  3273. {
  3274. // Set the annotation object which is currently placed
  3275. this.Chart.Annotations.placingAnnotation = this;
  3276. }
  3277. else
  3278. {
  3279. throw (new InvalidOperationException(SR.ExceptionAnnotationNotInCollection));
  3280. }
  3281. }
  3282. /// <summary>
  3283. /// Ends user placement of an annotation.
  3284. /// </summary>
  3285. /// <remarks>
  3286. /// Ends an annotation placement operation previously started by a
  3287. /// <see cref="BeginPlacement"/> method call.
  3288. /// <para>
  3289. /// Calling this method is not required, since placement will automatically
  3290. /// end when an end user enters all required points. However, it is useful when an annotation
  3291. /// placement operation needs to be aborted for some reason.
  3292. /// </para>
  3293. /// </remarks>
  3294. virtual public void EndPlacement()
  3295. {
  3296. if (this.Chart != null)
  3297. {
  3298. // Reset currently placed annotation object
  3299. this.Chart.Annotations.placingAnnotation = null;
  3300. // Restore default cursor
  3301. this.Chart.Cursor = this.Chart.defaultCursor;
  3302. // Clear last placement mouse position
  3303. this.lastPlacementPosition = PointF.Empty;
  3304. // Fire annotation placed event
  3305. this.Chart.OnAnnotationPlaced(this);
  3306. }
  3307. }
  3308. /// <summary>
  3309. /// Handles mouse down event during annotation placement.
  3310. /// </summary>
  3311. /// <param name="point">Mouse cursor position in pixels.</param>
  3312. /// <param name="buttons">Mouse button down.</param>
  3313. internal virtual void PlacementMouseDown(PointF point, MouseButtons buttons)
  3314. {
  3315. if (buttons == MouseButtons.Right)
  3316. {
  3317. // Stop any pacement
  3318. this.EndPlacement();
  3319. }
  3320. if (buttons == MouseButtons.Left &&
  3321. IsValidPlacementPosition(point.X, point.Y))
  3322. {
  3323. if (this.lastPlacementPosition.IsEmpty)
  3324. {
  3325. // Remeber position where mouse was clicked
  3326. this.lastPlacementPosition = this.GetGraphics().GetRelativePoint(point);
  3327. // Get annotation position in relative coordinates
  3328. PointF firstPoint = PointF.Empty;
  3329. PointF anchorPoint = PointF.Empty;
  3330. SizeF size = SizeF.Empty;
  3331. this.GetRelativePosition(out firstPoint, out size, out anchorPoint);
  3332. // Set annotation X, Y coordinate
  3333. if (this.AllowMoving)
  3334. {
  3335. firstPoint = this.GetGraphics().GetRelativePoint(point);
  3336. // Do not change default position
  3337. if (double.IsNaN(this.AnchorX))
  3338. {
  3339. anchorPoint.X = float.NaN;
  3340. }
  3341. if (double.IsNaN(this.AnchorY))
  3342. {
  3343. anchorPoint.Y = float.NaN;
  3344. }
  3345. }
  3346. else if (this.AllowAnchorMoving)
  3347. {
  3348. anchorPoint = this.GetGraphics().GetRelativePoint(point);
  3349. // Do not change default position
  3350. if (double.IsNaN(this.X))
  3351. {
  3352. firstPoint.X = float.NaN;
  3353. }
  3354. if (double.IsNaN(this.Y))
  3355. {
  3356. firstPoint.Y = float.NaN;
  3357. }
  3358. }
  3359. // Do not change default size
  3360. if (double.IsNaN(this.Width))
  3361. {
  3362. size.Width = float.NaN;
  3363. }
  3364. if (double.IsNaN(this.Height))
  3365. {
  3366. size.Height = float.NaN;
  3367. }
  3368. // Set annotation position
  3369. this.positionChanged = true;
  3370. this.SetPositionRelative(
  3371. new RectangleF(firstPoint, size),
  3372. anchorPoint,
  3373. true);
  3374. // Invalidate and update the chart
  3375. if (Chart != null)
  3376. {
  3377. Invalidate();
  3378. Chart.UpdateAnnotations();
  3379. }
  3380. }
  3381. }
  3382. }
  3383. /// <summary>
  3384. /// Handles mouse up event during annotation placement.
  3385. /// </summary>
  3386. /// <param name="point">Mouse cursor position in pixels.</param>
  3387. /// <param name="buttons">Mouse button Up.</param>
  3388. /// <returns>Return true when placing finished.</returns>
  3389. internal virtual bool PlacementMouseUp(PointF point, MouseButtons buttons)
  3390. {
  3391. bool result = false;
  3392. if (buttons == MouseButtons.Left)
  3393. {
  3394. // Get annotation position in relative coordinates
  3395. PointF firstPoint = PointF.Empty;
  3396. PointF anchorPoint = PointF.Empty;
  3397. SizeF size = SizeF.Empty;
  3398. this.GetRelativePosition(out firstPoint, out size, out anchorPoint);
  3399. if (this.AllowResizing)
  3400. {
  3401. PointF pointRel = this.GetGraphics().GetRelativePoint(point);
  3402. size = new SizeF(
  3403. pointRel.X - this.lastPlacementPosition.X,
  3404. pointRel.Y - this.lastPlacementPosition.Y);
  3405. }
  3406. else
  3407. {
  3408. // Do not change default size
  3409. if (double.IsNaN(this.Width))
  3410. {
  3411. size.Width = float.NaN;
  3412. }
  3413. if (double.IsNaN(this.Height))
  3414. {
  3415. size.Height = float.NaN;
  3416. }
  3417. }
  3418. // Do not change default position
  3419. if (double.IsNaN(this.X))
  3420. {
  3421. firstPoint.X = float.NaN;
  3422. }
  3423. if (double.IsNaN(this.Y))
  3424. {
  3425. firstPoint.Y = float.NaN;
  3426. }
  3427. if (double.IsNaN(this.AnchorX))
  3428. {
  3429. anchorPoint.X = float.NaN;
  3430. }
  3431. if (double.IsNaN(this.AnchorY))
  3432. {
  3433. anchorPoint.Y = float.NaN;
  3434. }
  3435. // Set annotation position
  3436. this.positionChanged = true;
  3437. this.SetPositionRelative(
  3438. new RectangleF(firstPoint, size),
  3439. anchorPoint,
  3440. true);
  3441. // End placement
  3442. if (!size.IsEmpty || !this.AllowResizing)
  3443. {
  3444. result = true;
  3445. this.EndPlacement();
  3446. }
  3447. // Invalidate and update the chart
  3448. if (Chart != null)
  3449. {
  3450. Invalidate();
  3451. Chart.UpdateAnnotations();
  3452. }
  3453. }
  3454. return result;
  3455. }
  3456. /// <summary>
  3457. /// Handles mouse move event during annotation placement.
  3458. /// </summary>
  3459. /// <param name="point">Mouse cursor position in pixels.</param>
  3460. internal virtual void PlacementMouseMove(PointF point)
  3461. {
  3462. // Check if annotation was moved
  3463. if (this.GetGraphics() != null &&
  3464. !this.lastPlacementPosition.IsEmpty)
  3465. {
  3466. // Get annotation position in relative coordinates
  3467. PointF firstPoint = PointF.Empty;
  3468. PointF anchorPoint = PointF.Empty;
  3469. SizeF size = SizeF.Empty;
  3470. this.GetRelativePosition(out firstPoint, out size, out anchorPoint);
  3471. if (this.AllowResizing)
  3472. {
  3473. PointF pointRel = this.GetGraphics().GetRelativePoint(point);
  3474. size = new SizeF(
  3475. pointRel.X - this.lastPlacementPosition.X,
  3476. pointRel.Y - this.lastPlacementPosition.Y);
  3477. }
  3478. // Do not change default position
  3479. if (double.IsNaN(this.X))
  3480. {
  3481. firstPoint.X = float.NaN;
  3482. }
  3483. if (double.IsNaN(this.Y))
  3484. {
  3485. firstPoint.Y = float.NaN;
  3486. }
  3487. if (double.IsNaN(this.AnchorX))
  3488. {
  3489. anchorPoint.X = float.NaN;
  3490. }
  3491. if (double.IsNaN(this.AnchorY))
  3492. {
  3493. anchorPoint.Y = float.NaN;
  3494. }
  3495. // Set annotation position
  3496. this.positionChanged = true;
  3497. this.SetPositionRelative(
  3498. new RectangleF(firstPoint, size),
  3499. anchorPoint,
  3500. true);
  3501. // Invalidate and update the chart
  3502. if (this.Chart != null)
  3503. {
  3504. Invalidate();
  3505. this.Chart.UpdateAnnotations();
  3506. }
  3507. }
  3508. }
  3509. /// <summary>
  3510. /// Checks if specified position is valid for placement.
  3511. /// </summary>
  3512. /// <param name="x">X coordinate.</param>
  3513. /// <param name="y">Y coordinate.</param>
  3514. /// <returns>True if annotation can be placed at specified coordinates.</returns>
  3515. virtual internal bool IsValidPlacementPosition(float x, float y)
  3516. {
  3517. if (this.Chart != null &&
  3518. this.GetGraphics() != null)
  3519. {
  3520. // Check if cursor is over the area where placement allowed
  3521. // If so - change cursor to cross
  3522. RectangleF placementRect = new RectangleF(0f, 0f, 100f, 100f);
  3523. if (this.ClipToChartArea.Length > 0 &&
  3524. this.ClipToChartArea != Constants.NotSetValue)
  3525. {
  3526. ChartArea area = Chart.ChartAreas[this.ClipToChartArea];
  3527. placementRect = area.PlotAreaPosition.ToRectangleF();
  3528. }
  3529. placementRect = this.GetGraphics().GetAbsoluteRectangle(placementRect);
  3530. if (placementRect.Contains(x, y))
  3531. {
  3532. return true;
  3533. }
  3534. }
  3535. return false;
  3536. }
  3537. #endregion // Placement Methods
  3538. #region Helper Methods
  3539. /// <summary>
  3540. /// Helper method that checks if annotation is visible.
  3541. /// </summary>
  3542. /// <returns>True if annotation is visible.</returns>
  3543. internal bool IsVisible()
  3544. {
  3545. if (this.Visible)
  3546. {
  3547. if (this.Chart != null)
  3548. {
  3549. // Check if annotation is anchored to the data point
  3550. ChartArea area = null;
  3551. if (this.AnchorDataPoint != null &&
  3552. this.AnchorDataPoint.series != null)
  3553. {
  3554. if (this.Chart.ChartAreas.IndexOf(this.AnchorDataPoint.series.ChartArea) >= 0)
  3555. {
  3556. area = this.Chart.ChartAreas[this.AnchorDataPoint.series.ChartArea];
  3557. }
  3558. }
  3559. if (area == null &&
  3560. this._anchorDataPoint2 != null &&
  3561. this._anchorDataPoint2.series != null)
  3562. {
  3563. if (this.Chart.ChartAreas.IndexOf(this._anchorDataPoint2.series.ChartArea) >= 0)
  3564. {
  3565. area = this.Chart.ChartAreas[this._anchorDataPoint2.series.ChartArea];
  3566. }
  3567. }
  3568. // Check if annotation uses chart area axis values
  3569. if (area == null && this.AxisX != null)
  3570. {
  3571. area = this.AxisX.ChartArea;
  3572. }
  3573. if (area == null && this.AxisY != null)
  3574. {
  3575. area = this.AxisY.ChartArea;
  3576. }
  3577. // Check if associated area is visible
  3578. if (area != null &&
  3579. !area.Visible)
  3580. {
  3581. return false;
  3582. }
  3583. }
  3584. return true;
  3585. }
  3586. return false;
  3587. }
  3588. /// <summary>
  3589. /// Resets pre-calculated annotation position.
  3590. /// </summary>
  3591. internal void ResetCurrentRelativePosition()
  3592. {
  3593. this.currentPositionRel = new RectangleF(float.NaN, float.NaN, float.NaN, float.NaN);
  3594. this.currentAnchorLocationRel = new PointF(float.NaN, float.NaN);
  3595. }
  3596. /// <summary>
  3597. /// Replaces predefined keyword inside the string with their values if
  3598. /// annotation is anchored to the data point.
  3599. /// </summary>
  3600. /// <param name="strOriginal">Original string with keywords.</param>
  3601. /// <returns>Modified string.</returns>
  3602. internal string ReplaceKeywords(string strOriginal)
  3603. {
  3604. if (this.AnchorDataPoint != null)
  3605. {
  3606. return this.AnchorDataPoint.ReplaceKeywords(strOriginal);
  3607. }
  3608. return strOriginal;
  3609. }
  3610. /// <summary>
  3611. /// Checks if anchor point of the annotation is visible.
  3612. /// </summary>
  3613. /// <returns>True if anchor point is visible.</returns>
  3614. internal bool IsAnchorVisible()
  3615. {
  3616. // Get axes objects
  3617. Axis vertAxis = null;
  3618. Axis horizAxis = null;
  3619. GetAxes(ref vertAxis, ref horizAxis);
  3620. // Get anchor position
  3621. bool inRelativeAnchorX = false;
  3622. bool inRelativeAnchorY = false;
  3623. double anchorX = this.AnchorX;
  3624. double anchorY = this.AnchorY;
  3625. GetAnchorLocation(ref anchorX, ref anchorY, ref inRelativeAnchorX, ref inRelativeAnchorY);
  3626. // Check if anchor is set
  3627. if (!double.IsNaN(anchorX) && !double.IsNaN(anchorY))
  3628. {
  3629. // Check if anchor is in axes coordinates
  3630. if (this.AnchorDataPoint != null ||
  3631. this.AxisX != null ||
  3632. this.AxisY != null)
  3633. {
  3634. // Convert anchor point to relative coordinates
  3635. if (!inRelativeAnchorX && horizAxis != null)
  3636. {
  3637. anchorX = horizAxis.ValueToPosition(anchorX);
  3638. }
  3639. if (!inRelativeAnchorY && vertAxis != null)
  3640. {
  3641. anchorY = vertAxis.ValueToPosition(anchorY);
  3642. }
  3643. // Get chart area
  3644. ChartArea chartArea = null;
  3645. if (horizAxis != null)
  3646. {
  3647. chartArea = horizAxis.ChartArea;
  3648. }
  3649. if (chartArea == null && vertAxis != null)
  3650. {
  3651. chartArea = vertAxis.ChartArea;
  3652. }
  3653. // Apply 3D transforamtion if required
  3654. if (chartArea != null && chartArea.Area3DStyle.Enable3D == true)
  3655. {
  3656. if (!chartArea.chartAreaIsCurcular &&
  3657. chartArea.requireAxes &&
  3658. chartArea.matrix3D.IsInitialized())
  3659. {
  3660. // Get anotation Z coordinate (use scene depth or anchored point Z position)
  3661. float positionZ = chartArea.areaSceneDepth;
  3662. if (this.AnchorDataPoint != null && this.AnchorDataPoint.series != null)
  3663. {
  3664. float depth = 0f;
  3665. chartArea.GetSeriesZPositionAndDepth(
  3666. this.AnchorDataPoint.series,
  3667. out depth,
  3668. out positionZ);
  3669. positionZ += depth / 2f;
  3670. }
  3671. // Define 3D points of annotation object
  3672. Point3D[] annot3DPoints = new Point3D[1];
  3673. annot3DPoints[0] = new Point3D((float)anchorX, (float)anchorY, positionZ);
  3674. // Tranform cube coordinates
  3675. chartArea.matrix3D.TransformPoints(annot3DPoints);
  3676. // Get transformed coordinates
  3677. anchorX = annot3DPoints[0].X;
  3678. anchorY = annot3DPoints[0].Y;
  3679. }
  3680. }
  3681. // Get plot rectangle position and inflate it slightly
  3682. // to solve any float rounding issues.
  3683. RectangleF rect = chartArea.PlotAreaPosition.ToRectangleF();
  3684. rect.Inflate(0.00001f, 0.00001f);
  3685. // Check if anchor point is in the plotting area
  3686. if (!rect.Contains((float)anchorX, (float)anchorY))
  3687. {
  3688. return false;
  3689. }
  3690. }
  3691. }
  3692. return true;
  3693. }
  3694. /// <summary>
  3695. /// Returns chart graphics objects.
  3696. /// </summary>
  3697. /// <returns>Chart graphics object.</returns>
  3698. internal ChartGraphics GetGraphics()
  3699. {
  3700. if (this.Common != null)
  3701. {
  3702. return this.Common.graph;
  3703. }
  3704. return null;
  3705. }
  3706. /// <summary>
  3707. /// Checks if provided pixel coordinate is contained in one of the
  3708. /// selection handles rectangle.
  3709. /// </summary>
  3710. /// <param name="point">Coordinate in pixels.</param>
  3711. /// <returns>Resizing mode.</returns>
  3712. internal ResizingMode GetSelectionHandle(PointF point)
  3713. {
  3714. ResizingMode resizingMode = ResizingMode.None;
  3715. if (this.Common != null &&
  3716. this.Common.graph != null)
  3717. {
  3718. // Convert point to relative coordinates
  3719. point = this.Common.graph.GetRelativePoint(point);
  3720. // Check if point is in one of the selection handles
  3721. if (this.selectionRects != null)
  3722. {
  3723. for (int index = 0; index < this.selectionRects.Length; index++)
  3724. {
  3725. if (!this.selectionRects[index].IsEmpty &&
  3726. this.selectionRects[index].Contains(point))
  3727. {
  3728. if (index > (int)ResizingMode.AnchorHandle)
  3729. {
  3730. resizingMode = ResizingMode.MovingPathPoints;
  3731. this.currentPathPointIndex = index - 9;
  3732. }
  3733. else
  3734. {
  3735. resizingMode = (ResizingMode)index;
  3736. }
  3737. }
  3738. }
  3739. }
  3740. }
  3741. return resizingMode;
  3742. }
  3743. /// <summary>
  3744. /// Gets data point X or Y axis.
  3745. /// </summary>
  3746. /// <param name="dataPoint">Data point to get the axis for.</param>
  3747. /// <param name="axisName">X or Y axis to get.</param>
  3748. /// <returns>Data point axis.</returns>
  3749. private Axis GetDataPointAxis(DataPoint dataPoint, AxisName axisName)
  3750. {
  3751. if (dataPoint != null && dataPoint.series != null && Chart != null)
  3752. {
  3753. // Get data point chart area
  3754. ChartArea chartArea = Chart.ChartAreas[dataPoint.series.ChartArea];
  3755. // Get point X axis
  3756. if ((axisName == AxisName.X || axisName == AxisName.X2) &&
  3757. !chartArea.switchValueAxes)
  3758. {
  3759. return chartArea.GetAxis(axisName, dataPoint.series.XAxisType, dataPoint.series.XSubAxisName);
  3760. }
  3761. else
  3762. {
  3763. return chartArea.GetAxis(axisName, dataPoint.series.YAxisType, dataPoint.series.YSubAxisName);
  3764. }
  3765. }
  3766. return null;
  3767. }
  3768. /// <summary>
  3769. /// Gets annotation vertical and horizontal axes.
  3770. /// </summary>
  3771. /// <param name="vertAxis">Returns annotation vertical axis or null.</param>
  3772. /// <param name="horizAxis">Returns annotation horizontal axis or null.</param>
  3773. internal void GetAxes(ref Axis vertAxis, ref Axis horizAxis)
  3774. {
  3775. vertAxis = null;
  3776. horizAxis = null;
  3777. if (this.AxisX != null && this.AxisX.ChartArea != null)
  3778. {
  3779. if (this.AxisX.ChartArea.switchValueAxes)
  3780. {
  3781. vertAxis = this.AxisX;
  3782. }
  3783. else
  3784. {
  3785. horizAxis = this.AxisX;
  3786. }
  3787. }
  3788. if (this.AxisY != null && this.AxisY.ChartArea != null)
  3789. {
  3790. if (this.AxisY.ChartArea.switchValueAxes)
  3791. {
  3792. horizAxis = this.AxisY;
  3793. }
  3794. else
  3795. {
  3796. vertAxis = this.AxisY;
  3797. }
  3798. }
  3799. // Get axes from attached data point
  3800. if (this.AnchorDataPoint != null)
  3801. {
  3802. if (horizAxis == null)
  3803. {
  3804. horizAxis = GetDataPointAxis(this.AnchorDataPoint, AxisName.X);
  3805. // For chart types like Bar, RangeBar and others, position of X and Y axes are flipped
  3806. if (horizAxis != null && horizAxis.ChartArea != null && horizAxis.ChartArea.switchValueAxes)
  3807. {
  3808. horizAxis = GetDataPointAxis(this.AnchorDataPoint, AxisName.Y);
  3809. }
  3810. }
  3811. if (vertAxis == null)
  3812. {
  3813. vertAxis = GetDataPointAxis(this.AnchorDataPoint, AxisName.Y);
  3814. // For chart types like Bar, RangeBar and others, position of X and Y axes are flipped
  3815. if (vertAxis != null && vertAxis.ChartArea != null && vertAxis.ChartArea.switchValueAxes)
  3816. {
  3817. vertAxis = GetDataPointAxis(this.AnchorDataPoint, AxisName.X);
  3818. }
  3819. }
  3820. }
  3821. // No axes coordinate system for grouped annotations
  3822. if (vertAxis != null || horizAxis != null)
  3823. {
  3824. if (this.AnnotationGroup != null)
  3825. {
  3826. throw (new InvalidOperationException(SR.ExceptionAnnotationGroupedAxisMustBeEmpty));
  3827. }
  3828. }
  3829. }
  3830. #endregion
  3831. #endregion
  3832. #region IDisposable Members
  3833. /// <summary>
  3834. /// Releases unmanaged and - optionally - managed resources
  3835. /// </summary>
  3836. /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
  3837. protected override void Dispose(bool disposing)
  3838. {
  3839. if (disposing)
  3840. {
  3841. //Free managed resources
  3842. if (_fontCache != null)
  3843. {
  3844. _fontCache.Dispose();
  3845. _fontCache = null;
  3846. }
  3847. }
  3848. base.Dispose(disposing);
  3849. }
  3850. #endregion
  3851. }
  3852. /// <summary>
  3853. /// This class is used to stores position changing event data for an annotation.
  3854. /// </summary>
  3855. /// <remarks>
  3856. /// Provides additional data like the new annotation and anchor position when an end user
  3857. /// is moving the annotation with the mouse.
  3858. /// <para>
  3859. /// Can be used to restrict annotation movement, or snap the annotation position to
  3860. /// specific points.
  3861. /// </para>
  3862. /// </remarks>
  3863. [
  3864. SRDescription("DescriptionAttributeAnnotationPositionChangingEventArgs_AnnotationPositionChangingEventArgs"),
  3865. ]
  3866. public class AnnotationPositionChangingEventArgs : EventArgs
  3867. {
  3868. #region Fields
  3869. private Annotation _Annotation = null;
  3870. /// <summary>
  3871. /// Gets or sets the annotation the event is fired for.
  3872. /// </summary>
  3873. public Annotation Annotation
  3874. {
  3875. get { return _Annotation; }
  3876. set { _Annotation = value; }
  3877. }
  3878. private double _NewLocationX = 0.0;
  3879. /// <summary>
  3880. /// Gets or sets the new X location of the annotation.
  3881. /// </summary>
  3882. public double NewLocationX
  3883. {
  3884. get { return _NewLocationX; }
  3885. set { _NewLocationX = value; }
  3886. }
  3887. private double _NewLocationY = 0.0;
  3888. /// <summary>
  3889. /// Gets or sets the new Y location of the annotation.
  3890. /// </summary>
  3891. public double NewLocationY
  3892. {
  3893. get { return _NewLocationY; }
  3894. set { _NewLocationY = value; }
  3895. }
  3896. private double _NewSizeWidth = 0.0;
  3897. /// <summary>
  3898. /// Gets or sets the new width of the annotation.
  3899. /// </summary>
  3900. public double NewSizeWidth
  3901. {
  3902. get { return _NewSizeWidth; }
  3903. set { _NewSizeWidth = value; }
  3904. }
  3905. private double _NewSizeHeight = 0.0;
  3906. /// <summary>
  3907. /// Gets or sets the new height of the annotation.
  3908. /// </summary>
  3909. public double NewSizeHeight
  3910. {
  3911. get { return _NewSizeHeight; }
  3912. set { _NewSizeHeight = value; }
  3913. }
  3914. private double _NewAnchorLocationX = 0.0;
  3915. /// <summary>
  3916. /// Gets or sets the new annotation anchor point X location.
  3917. /// </summary>
  3918. public double NewAnchorLocationX
  3919. {
  3920. get { return _NewAnchorLocationX; }
  3921. set { _NewAnchorLocationX = value; }
  3922. }
  3923. private double _NewAnchorLocationY = 0.0;
  3924. /// <summary>
  3925. /// Gets or sets the new annotation anchor point Y location.
  3926. /// </summary>
  3927. public double NewAnchorLocationY
  3928. {
  3929. get { return _NewAnchorLocationY; }
  3930. set { _NewAnchorLocationY = value; }
  3931. }
  3932. #endregion // Fields
  3933. #region Properties
  3934. /// <summary>
  3935. /// Gets or sets the new location and size of the annotation.
  3936. /// </summary>
  3937. [
  3938. Browsable(false),
  3939. EditorBrowsableAttribute(EditorBrowsableState.Never),
  3940. ]
  3941. public RectangleF NewPosition
  3942. {
  3943. get
  3944. {
  3945. return new RectangleF(
  3946. (float)this.NewLocationX,
  3947. (float)this.NewLocationY,
  3948. (float)this.NewSizeWidth,
  3949. (float)this.NewSizeHeight);
  3950. }
  3951. set
  3952. {
  3953. this.NewLocationX = value.X;
  3954. this.NewLocationY = value.Y;
  3955. this.NewSizeWidth = value.Width;
  3956. this.NewSizeHeight = value.Height;
  3957. }
  3958. }
  3959. /// <summary>
  3960. /// Gets or sets the new anchor location of the annotation.
  3961. /// </summary>
  3962. [
  3963. Browsable(false),
  3964. EditorBrowsableAttribute(EditorBrowsableState.Never),
  3965. ]
  3966. public PointF NewAnchorLocation
  3967. {
  3968. get
  3969. {
  3970. return new PointF(
  3971. (float)this.NewAnchorLocationX,
  3972. (float)this.NewAnchorLocationY);
  3973. }
  3974. set
  3975. {
  3976. this.NewAnchorLocationX = value.X;
  3977. this.NewAnchorLocationY = value.Y;
  3978. }
  3979. }
  3980. #endregion // Properties
  3981. }
  3982. }