Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Web.DataVisualization / Common / Annotation / TextAnnotation.cs
1 //-------------------------------------------------------------
2 // <copyright company=\92Microsoft Corporation\92>
3 //   Copyright © Microsoft Corporation. All Rights Reserved.
4 // </copyright>
5 //-------------------------------------------------------------
6 // @owner=alexgor, deliant
7 //=================================================================
8 //  File:               TextAnnotation.cs
9 //
10 //  Namespace:  System.Web.UI.WebControls[Windows.Forms].Charting
11 //
12 //      Classes:        TextAnnotation, AnnotationSmartLabelStyle
13 //
14 //  Purpose:    Text annotation class.
15 //
16 //      Reviewed:       
17 //
18 //===================================================================
19
20 #region Used namespace
21 using System;
22 using System.Collections;
23 using System.Collections.Specialized;
24 using System.ComponentModel;
25 using System.ComponentModel.Design;
26 using System.Data;
27 using System.Drawing;
28 using System.Drawing.Design;
29 using System.Drawing.Text;
30 using System.Drawing.Drawing2D;
31 using System.Security;
32
33 #if Microsoft_CONTROL
34 using System.Windows.Forms;
35         using System.Windows.Forms.DataVisualization.Charting;
36         using System.Windows.Forms.DataVisualization.Charting.Data;
37         using System.Windows.Forms.DataVisualization.Charting.ChartTypes;
38         using System.Windows.Forms.DataVisualization.Charting.Utilities;
39         using System.Windows.Forms.DataVisualization.Charting.Borders3D;
40 #else
41 using System.Web;
42 using System.Web.UI;
43 using System.Web.UI.DataVisualization.Charting;
44 using System.Web.UI.DataVisualization.Charting.Data;
45 using System.Web.UI.DataVisualization.Charting.Utilities;
46 #endif
47
48
49 #endregion
50
51 #if Microsoft_CONTROL
52         namespace System.Windows.Forms.DataVisualization.Charting
53 #else
54 namespace System.Web.UI.DataVisualization.Charting
55
56 #endif
57 {
58         /// <summary>
59         /// <b>TextAnnotation</b> is a class that represents a text annotation.
60         /// </summary>
61         /// <remarks>
62         /// Note that other annotations do display inner text (e.g. rectangle, 
63         /// ellipse annotations.).
64         /// </remarks>
65         [
66                 SRDescription("DescriptionAttributeTextAnnotation_TextAnnotation"),
67         ]
68 #if ASPPERM_35
69         [AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
70     [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
71 #endif
72     public class TextAnnotation : Annotation
73         {
74                 #region Fields
75
76                 // Annotation text
77                 private         string                  _text = "";
78
79                 // Indicates multiline text
80                 private         bool                    _isMultiline = false;
81
82                 // Current content size
83                 internal        SizeF                   contentSize = SizeF.Empty;
84
85                 // Indicates that annotion is an ellipse
86                 internal        bool                    isEllipse = false;
87
88 #if Microsoft_CONTROL
89
90                 // Control used to edit text
91                 private         TextBox                 _editTextBox = null;
92
93 #endif // Microsoft_CONTROL
94
95                 #endregion
96
97                 #region Construction and Initialization
98
99                 /// <summary>
100                 /// Default public constructor.
101                 /// </summary>
102                 public TextAnnotation() 
103             : base()
104                 {
105                 }
106
107                 #endregion
108
109                 #region Properties
110
111                 #region Text Visual Attributes
112
113                 /// <summary>
114                 /// Annotation's text.
115                 /// </summary>
116                 [
117                 SRCategory("CategoryAttributeAppearance"),
118                 DefaultValue(""),
119                 SRDescription("DescriptionAttributeText"),
120                 ]
121                 virtual public string Text
122                 {
123                         get
124                         {
125                                 return _text;
126                         }
127                         set
128                         {
129                                 _text = value;
130                                 Invalidate();
131
132                                 // Reset content size to empty
133                                 contentSize = SizeF.Empty;
134                         }
135                 }
136
137                 /// <summary>
138                 /// Indicates whether the annotation text is multiline.
139                 /// </summary>
140                 [
141                 SRCategory("CategoryAttributeAppearance"),
142                 DefaultValue(false),
143                 SRDescription("DescriptionAttributeMultiline"),
144                 ]
145                 virtual public bool IsMultiline
146                 {
147                         get
148                         {
149                                 return _isMultiline;
150                         }
151                         set
152                         {
153                                 _isMultiline = value;
154                                 Invalidate();
155                         }
156                 }
157
158         /// <summary>
159         /// Gets or sets the font of an annotation's text.
160         /// <seealso cref="Annotation.ForeColor"/>
161         /// </summary>
162         /// <value>
163         /// A <see cref="Font"/> object used for an annotation's text.
164         /// </value>
165                 [
166                 SRCategory("CategoryAttributeAppearance"),
167                 DefaultValue(typeof(Font), "Microsoft Sans Serif, 8pt"),
168                 SRDescription("DescriptionAttributeTextFont4"),
169                 ]
170                 override public Font Font
171                 {
172                         get
173                         {
174                                 return base.Font;
175                         }
176                         set
177                         {
178                                 base.Font = value;
179
180                                 // Reset content size to empty
181                                 contentSize = SizeF.Empty;
182                         }
183                 }
184
185                 #endregion
186
187                 #region Non Applicable Annotation Appearance Attributes (set as Non-Browsable)
188
189                 /// <summary>
190                 /// Not applicable to this annotation type.
191                 /// </summary>
192                 [
193                 SRCategory("CategoryAttributeAppearance"),
194                 Browsable(false),
195                 DefaultValue(typeof(Color), "Black"),
196         TypeConverter(typeof(ColorConverter)),
197         Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base)
198                 ]
199                 override public Color LineColor
200                 {
201                         get
202                         {
203                                 return base.LineColor;
204                         }
205                         set
206                         {
207                                 base.LineColor = value;
208                         }
209                 }
210
211                 /// <summary>
212                 /// Not applicable to this annotation type.
213                 /// </summary>
214                 [
215                 SRCategory("CategoryAttributeAppearance"),
216                 Browsable(false),
217                 DefaultValue(1),
218         SRDescription("DescriptionAttributeLineWidth"),
219                 ]
220                 override public int LineWidth
221                 {
222                         get
223                         {
224                                 return base.LineWidth;
225                         }
226                         set
227                         {
228                                 base.LineWidth = value;
229
230                         }
231                 }
232
233                 /// <summary>
234                 /// Not applicable to this annotation type.
235                 /// </summary>
236                 [
237                 SRCategory("CategoryAttributeAppearance"),
238                 Browsable(false),
239                 DefaultValue(ChartDashStyle.Solid),
240                 ]
241                 override public ChartDashStyle LineDashStyle
242                 {
243                         get
244                         {
245                                 return base.LineDashStyle;
246                         }
247                         set
248                         {
249                                 base.LineDashStyle = value;
250                         }
251                 }
252
253                 /// <summary>
254                 /// Not applicable to this annotation type.
255                 /// </summary>
256                 [
257                 SRCategory("CategoryAttributeAppearance"),
258                 Browsable(false),
259                 DefaultValue(typeof(Color), ""),
260                 NotifyParentPropertyAttribute(true),
261         TypeConverter(typeof(ColorConverter)),
262         Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base)
263                 ]
264                 override public Color BackColor
265                 {
266                         get
267                         {
268                                 return base.BackColor;
269                         }
270                         set
271                         {
272                                 base.BackColor = value;
273                         }
274                 }
275
276                 /// <summary>
277                 /// Not applicable to this annotation type.
278                 /// </summary>
279                 [
280                 SRCategory("CategoryAttributeAppearance"),
281                 Browsable(false),
282                 DefaultValue(ChartHatchStyle.None),
283                 NotifyParentPropertyAttribute(true),
284                 Editor(Editors.HatchStyleEditor.Editor, Editors.HatchStyleEditor.Base)
285                 ]
286                 override public ChartHatchStyle BackHatchStyle
287                 {
288                         get
289                         {
290                                 return base.BackHatchStyle;
291                         }
292                         set
293                         {
294                                 base.BackHatchStyle = value;
295                         }
296                 }
297
298                 /// <summary>
299                 /// Not applicable to this annotation type.
300                 /// </summary>
301                 [
302                 SRCategory("CategoryAttributeAppearance"),
303                 Browsable(false),
304                 DefaultValue(GradientStyle.None),
305                 NotifyParentPropertyAttribute(true),
306                 Editor(Editors.GradientEditor.Editor, Editors.GradientEditor.Base)
307                 ]               
308                 override public GradientStyle BackGradientStyle
309                 {
310                         get
311                         {
312                                 return base.BackGradientStyle;
313                         }
314                         set
315                         {
316                                 base.BackGradientStyle = value;
317                         }
318                 }
319
320                 /// <summary>
321                 /// Not applicable to this annotation type.
322                 /// </summary>
323                 [
324                 SRCategory("CategoryAttributeAppearance"),
325                 Browsable(false),
326                 DefaultValue(typeof(Color), ""),
327                 NotifyParentPropertyAttribute(true),
328         TypeConverter(typeof(ColorConverter)),
329         Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base)
330                 ] 
331                 override public Color BackSecondaryColor
332                 {
333                         get
334                         {
335                                 return base.BackSecondaryColor;
336                         }
337                         set
338                         {
339                                 base.BackSecondaryColor = value;
340                         }
341                 }
342
343                 #endregion
344
345                 #region Other
346
347         /// <summary>
348         /// Gets or sets an annotation's type name.
349         /// </summary>
350         /// <remarks>
351         /// This property is used to get the name of each annotation type 
352         /// (e.g. Line, Rectangle, Ellipse). 
353         /// <para>
354         /// This property is for internal use and is hidden at design and run time.
355         /// </para>
356         /// </remarks>
357                 [
358                 SRCategory("CategoryAttributeMisc"),
359                 Bindable(true),
360                 Browsable(false),
361                 EditorBrowsableAttribute(EditorBrowsableState.Never),
362                 DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
363                 SerializationVisibilityAttribute(SerializationVisibility.Hidden),
364                 SRDescription("DescriptionAttributeTextAnnotation_AnnotationType"),
365                 ]
366                 public override string AnnotationType
367                 {
368                         get
369                         {
370                                 return "Text";
371                         }
372                 }
373
374                 /// <summary>
375                 /// Annotation selection points style.
376                 /// </summary>
377                 [
378                 SRCategory("CategoryAttributeAppearance"),
379                 DefaultValue(SelectionPointsStyle.Rectangle),
380                 ParenthesizePropertyNameAttribute(true),
381                 Browsable(false),
382                 EditorBrowsableAttribute(EditorBrowsableState.Never),
383                 DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
384                 SerializationVisibilityAttribute(SerializationVisibility.Hidden),
385                 SRDescription("DescriptionAttributeSelectionPointsStyle"),
386                 ]
387                 override internal SelectionPointsStyle SelectionPointsStyle
388                 {
389                         get
390                         {
391                                 return SelectionPointsStyle.Rectangle;
392                         }
393                 }
394
395                 #endregion
396
397                 #endregion
398
399                 #region Methods
400
401                 #region Painting
402
403                 /// <summary>
404                 /// Paints an annotation object on the specified graphics.
405                 /// </summary>
406                 /// <param name="graphics">
407                 /// A <see cref="ChartGraphics"/> object, used to paint an annotation object.
408                 /// </param>
409                 /// <param name="chart">
410                 /// Reference to the <see cref="Chart"/> owner control.
411                 /// </param>
412         override internal void Paint(Chart chart, ChartGraphics graphics)
413                 {
414                         // Get annotation position in relative coordinates
415                         PointF firstPoint = PointF.Empty;
416                         PointF anchorPoint = PointF.Empty;
417                         SizeF size = SizeF.Empty;
418                         GetRelativePosition(out firstPoint, out size, out anchorPoint);
419                         PointF  secondPoint = new PointF(firstPoint.X + size.Width, firstPoint.Y + size.Height);
420
421                         // Create selection rectangle
422                         RectangleF selectionRect = new RectangleF(firstPoint, new SizeF(secondPoint.X - firstPoint.X, secondPoint.Y - firstPoint.Y));
423
424                         // Get text position
425                         RectangleF      textPosition = new RectangleF(selectionRect.Location, selectionRect.Size);
426                         if(textPosition.Width < 0)
427                         {
428                                 textPosition.X = textPosition.Right;
429                                 textPosition.Width = -textPosition.Width;
430                         }
431                         if(textPosition.Height < 0)
432                         {
433                                 textPosition.Y = textPosition.Bottom;
434                                 textPosition.Height = -textPosition.Height;
435                         }
436
437                         // Check if text position is valid
438                         if( textPosition.IsEmpty ||
439                                 float.IsNaN(textPosition.X) || 
440                                 float.IsNaN(textPosition.Y) || 
441                                 float.IsNaN(textPosition.Right) || 
442                                 float.IsNaN(textPosition.Bottom) )
443                         {
444                                 return;
445                         }
446
447                         if(this.Common.ProcessModePaint)
448                         {
449                                 DrawText(graphics, textPosition, false, false);
450                         }
451
452                         if(this.Common.ProcessModeRegions)
453                         {
454                                 // Add hot region
455                                 if(isEllipse)
456                                 {
457                     using (GraphicsPath ellipsePath = new GraphicsPath())
458                     {
459                         ellipsePath.AddEllipse(textPosition);
460                         this.Common.HotRegionsList.AddHotRegion(
461                             graphics,
462                             ellipsePath,
463                             true,
464                             ReplaceKeywords(this.ToolTip),
465 #if Microsoft_CONTROL
466                                                 String.Empty,
467                                                 String.Empty,
468                                                 String.Empty,
469 #else // Microsoft_CONTROL
470  ReplaceKeywords(this.Url),
471                                 ReplaceKeywords(this.MapAreaAttributes),
472                 ReplaceKeywords(this.PostBackValue),
473 #endif // Microsoft_CONTROL
474  this,
475                             ChartElementType.Annotation);
476                     }
477                                 }
478                                 else
479                                 {
480                                         this.Common.HotRegionsList.AddHotRegion(
481                                                 textPosition,
482                                                 ReplaceKeywords(this.ToolTip),
483 #if Microsoft_CONTROL
484                                                 String.Empty,
485                                                 String.Empty,
486                                                 String.Empty,
487 #else // Microsoft_CONTROL
488                         ReplaceKeywords(this.Url),
489                                             ReplaceKeywords(this.MapAreaAttributes),
490                         ReplaceKeywords(this.PostBackValue),
491 #endif // Microsoft_CONTROL
492                                                 this,
493                                                 ChartElementType.Annotation,
494                                                 String.Empty);
495                                 }
496                         }
497
498                         // Paint selection handles
499                         PaintSelectionHandles(graphics, selectionRect, null);
500                 }
501
502                 /// <summary>
503                 /// Draws text in specified rectangle.
504                 /// </summary>
505                 /// <param name="graphics">Chart graphics.</param>
506                 /// <param name="textPosition">Text position.</param>
507                 /// <param name="noSpacingForCenteredText">True if text allowed to be outside of position when centered.</param>
508                 /// <param name="getTextPosition">True if position text must be returned by the method.</param>
509                 /// <returns>Text actual position if required.</returns>
510                 internal RectangleF DrawText(ChartGraphics graphics, RectangleF textPosition, bool noSpacingForCenteredText, bool getTextPosition)
511                 {
512                         RectangleF      textActualPosition = RectangleF.Empty;
513
514                         //***************************************************************
515                         //** Adjust text position uing text spacing
516                         //***************************************************************
517                         bool annotationRelative = false;
518                         RectangleF      textSpacing = GetTextSpacing(out annotationRelative);
519                         float spacingScaleX = 1f;
520                         float spacingScaleY = 1f;
521                         if(annotationRelative)
522                         {
523                                 if(textPosition.Width > 25f)
524                                 {
525                                         spacingScaleX = textPosition.Width / 50f;
526                                         spacingScaleX = Math.Max(1f, spacingScaleX);
527                                 }
528                                 if(textPosition.Height > 25f)
529                                 {
530                                         spacingScaleY = textPosition.Height / 50f;
531                                         spacingScaleY = Math.Max(1f, spacingScaleY);
532                                 }
533                         }
534
535                         RectangleF      textPositionWithSpacing = new RectangleF(textPosition.Location, textPosition.Size);
536                         textPositionWithSpacing.Width -= (textSpacing.Width + textSpacing.X) * spacingScaleX;
537                         textPositionWithSpacing.X += textSpacing.X * spacingScaleX;
538                         textPositionWithSpacing.Height -= (textSpacing.Height + textSpacing.Y) * spacingScaleY;
539                         textPositionWithSpacing.Y += textSpacing.Y * spacingScaleY;
540
541                         //***************************************************************
542                         //** Replace new line characters
543                         //***************************************************************
544                         string titleText = this.ReplaceKeywords(this.Text.Replace("\\n", "\n"));
545
546                         //***************************************************************
547                         //** Check if centered text require spacing.
548                         //** Use only half of the spacing required.
549                         //** Apply only for 1 line of text.
550                         //***************************************************************
551                         if(noSpacingForCenteredText &&
552                                 titleText.IndexOf('\n') == -1)
553                         {
554                                 if(this.Alignment == ContentAlignment.MiddleCenter ||
555                                         this.Alignment == ContentAlignment.MiddleLeft ||
556                                         this.Alignment == ContentAlignment.MiddleRight)
557                                 {
558                                         textPositionWithSpacing.Y = textPosition.Y;
559                                         textPositionWithSpacing.Height = textPosition.Height;
560                                         textPositionWithSpacing.Height -= textSpacing.Height/2f + textSpacing.Y / 2f;
561                                         textPositionWithSpacing.Y += textSpacing.Y / 2f;
562                                 }
563                                 if(this.Alignment == ContentAlignment.BottomCenter ||
564                                         this.Alignment == ContentAlignment.MiddleCenter ||
565                                         this.Alignment == ContentAlignment.TopCenter)
566                                 {
567                                         textPositionWithSpacing.X = textPosition.X;
568                                         textPositionWithSpacing.Width = textPosition.Width;
569                                         textPositionWithSpacing.Width -= textSpacing.Width/2f + textSpacing.X / 2f;
570                                         textPositionWithSpacing.X += textSpacing.X / 2f;
571                                 }
572                         }
573
574                         // Draw text
575                         using( Brush textBrush = new SolidBrush(this.ForeColor) )
576                         {
577                 using (StringFormat format = new StringFormat(StringFormat.GenericTypographic))
578                 {
579                     //***************************************************************
580                                     //** Set text format
581                                     //***************************************************************
582                     format.FormatFlags = format.FormatFlags ^ StringFormatFlags.LineLimit;
583                     format.Trimming = StringTrimming.EllipsisCharacter;
584                     if (this.Alignment == ContentAlignment.BottomRight ||
585                         this.Alignment == ContentAlignment.MiddleRight ||
586                         this.Alignment == ContentAlignment.TopRight)
587                     {
588                         format.Alignment = StringAlignment.Far;
589                     }
590                     if (this.Alignment == ContentAlignment.BottomCenter ||
591                         this.Alignment == ContentAlignment.MiddleCenter ||
592                         this.Alignment == ContentAlignment.TopCenter)
593                     {
594                         format.Alignment = StringAlignment.Center;
595                     }
596                     if (this.Alignment == ContentAlignment.BottomCenter ||
597                         this.Alignment == ContentAlignment.BottomLeft ||
598                         this.Alignment == ContentAlignment.BottomRight)
599                     {
600                         format.LineAlignment = StringAlignment.Far;
601                     }
602                     if (this.Alignment == ContentAlignment.MiddleCenter ||
603                         this.Alignment == ContentAlignment.MiddleLeft ||
604                         this.Alignment == ContentAlignment.MiddleRight)
605                     {
606                         format.LineAlignment = StringAlignment.Center;
607                     }
608
609                     //***************************************************************
610                     //** Set shadow color and offset
611                     //***************************************************************
612                     Color textShadowColor = ChartGraphics.GetGradientColor(this.ForeColor, Color.Black, 0.8);
613                     int textShadowOffset = 1;
614                     TextStyle textStyle = this.TextStyle;
615                     if (textStyle == TextStyle.Shadow &&
616                         ShadowOffset != 0)
617                     {
618                         // Draw shadowed text
619                         textShadowColor = ShadowColor;
620                         textShadowOffset = ShadowOffset;
621                     }
622
623                     if (textStyle == TextStyle.Shadow)
624                     {
625                         textShadowColor = (textShadowColor.A != 255) ? textShadowColor : Color.FromArgb(textShadowColor.A / 2, textShadowColor);
626                     }
627
628                     //***************************************************************
629                     //** Get text actual position
630                     //***************************************************************
631                     if (getTextPosition)
632                     {
633                         // Measure text size
634                         SizeF textSize = graphics.MeasureStringRel(
635                             this.ReplaceKeywords(_text.Replace("\\n", "\n")),
636                             this.Font,
637                             textPositionWithSpacing.Size,
638                             format);
639
640                         // Get text position
641                         textActualPosition = new RectangleF(textPositionWithSpacing.Location, textSize);
642                         if (this.Alignment == ContentAlignment.BottomRight ||
643                             this.Alignment == ContentAlignment.MiddleRight ||
644                             this.Alignment == ContentAlignment.TopRight)
645                         {
646                             textActualPosition.X += textPositionWithSpacing.Width - textSize.Width;
647                         }
648                         if (this.Alignment == ContentAlignment.BottomCenter ||
649                             this.Alignment == ContentAlignment.MiddleCenter ||
650                             this.Alignment == ContentAlignment.TopCenter)
651                         {
652                             textActualPosition.X += (textPositionWithSpacing.Width - textSize.Width) / 2f;
653                         }
654                         if (this.Alignment == ContentAlignment.BottomCenter ||
655                             this.Alignment == ContentAlignment.BottomLeft ||
656                             this.Alignment == ContentAlignment.BottomRight)
657                         {
658                             textActualPosition.Y += textPositionWithSpacing.Height - textSize.Height;
659                         }
660                         if (this.Alignment == ContentAlignment.MiddleCenter ||
661                             this.Alignment == ContentAlignment.MiddleLeft ||
662                             this.Alignment == ContentAlignment.MiddleRight)
663                         {
664                             textActualPosition.Y += (textPositionWithSpacing.Height - textSize.Height) / 2f;
665                         }
666
667                         // Do not allow text to go outside annotation position
668                         textActualPosition.Intersect(textPositionWithSpacing);
669                     }
670
671                     RectangleF  absPosition = graphics.GetAbsoluteRectangle(textPositionWithSpacing);
672                     Title.DrawStringWithStyle(
673                             graphics, 
674                             titleText, 
675                             this.TextStyle, 
676                             this.Font, 
677                             absPosition, 
678                             this.ForeColor, 
679                             textShadowColor, 
680                             textShadowOffset, 
681                             format, 
682                             TextOrientation.Auto
683                       );
684                 }
685                         }
686
687                         return textActualPosition;
688                 }
689
690                 #endregion      // Painting
691
692                 #region Text Editing
693
694 #if Microsoft_CONTROL
695
696                 /// <summary>
697                 /// Stops editing of the annotation text.
698                 /// <seealso cref="BeginTextEditing"/>
699                 /// </summary>
700                 /// <remarks>
701                 /// Call this method to cancel text editing, which was started via a call to 
702                 /// the <see cref="BeginTextEditing"/> method, or after the end-user double-clicks 
703                 /// on the annotation.
704                 /// </remarks>
705                 public void StopTextEditing()
706                 {
707                         // Check if text is currently edited
708                         if(_editTextBox != null)
709                         {
710                                 // Set annotation text
711                                 this.Text = _editTextBox.Text;
712
713                                 // Remove and dispose the text box
714                                 try
715                                 {
716                                         _editTextBox.KeyDown -= new KeyEventHandler(OnTextBoxKeyDown);
717                                         _editTextBox.LostFocus -= new EventHandler(OnTextBoxLostFocus);
718                                 }
719                                 catch(SecurityException)
720                                 {
721                                         // Ignore security issues
722                                 }
723                                 
724                                 if(this.Chart.Controls.Contains(_editTextBox))
725                                 {
726                                         TextBox tempControl = null;
727                                         try
728                                         {
729                                                 // NOTE: Workaround .Net bug. Issue with appplication closing if
730                                                 // active control is removed.
731                                                 Form parentForm = this.Chart.FindForm();
732                                                 if(parentForm != null)
733                                                 {
734                                                         tempControl = new TextBox();
735                                                         tempControl.Visible = false;
736                         
737                                                         // Add temp. control as active
738                                                         parentForm.Controls.Add(tempControl);
739                                                         parentForm.ActiveControl = tempControl;
740                                                 }
741                                         }
742                                         catch(SecurityException)
743                                         {
744                                                 // Ignore security issues
745                                         }
746
747                                         // Remove text editor
748                                         this.Chart.Controls.Remove(_editTextBox);
749
750                                         // Dispose temp. text box
751                                         if(tempControl != null)
752                                         {
753                                                 tempControl.Dispose();
754                                         }
755                                 }
756
757                                 // Dispose edit box
758                                 _editTextBox.Dispose();
759                                 _editTextBox = null;
760
761                                 // Raise notification event
762                                 if(this.Chart != null)
763                                 {
764                                         this.Chart.OnAnnotationTextChanged(this);
765                                 }
766
767                                 // Update chart
768                                 if(this.Chart != null)
769                                 {
770                                         this.Chart.Invalidate();
771                                         this.Chart.Update();
772                                 }
773
774                         }
775                 }
776
777                 /// <summary>
778                 /// Handles event when focus is lost by the text editing control.
779                 /// </summary>
780                 /// <param name="sender">Event sender.</param>
781                 /// <param name="e">Event arguments.</param>
782                 private void OnTextBoxLostFocus(object sender, EventArgs e)
783                 {
784                         StopTextEditing();
785                 }
786
787                 /// <summary>
788                 /// Handles event when key is pressed in the text editing control.
789                 /// </summary>
790                 /// <param name="sender">Event sender.</param>
791                 /// <param name="e">Event arguments.</param>
792                 private void OnTextBoxKeyDown(object sender, KeyEventArgs e)
793                 {
794                         if(e.KeyCode == Keys.Escape)
795                         {
796                                 // Reset text and stop editing
797                                 _editTextBox.Text = this.Text;
798                                 StopTextEditing();
799                         }
800                         else if(e.KeyCode == Keys.Enter &&
801                                 this.IsMultiline == false)
802                         {
803                                 // Stop editing
804                                 StopTextEditing();
805                         }
806                 }
807
808                 /// <summary>
809                 /// Begins editing the annotation's text by an end user.
810                 /// <seealso cref="StopTextEditing"/>
811                 /// </summary>
812                 /// <remarks>
813                 /// After calling this method, the annotation displays an editing box which allows 
814                 /// for editing of the annotation's text.
815                 /// <para>
816                 /// Call the <see cref="StopTextEditing"/> method to cancel this mode programatically.  
817                 /// Note that editing ends when the end-user hits the <c>Enter</c> key if multi-line 
818                 /// is false, or when the end-user clicks outside of the editing box if multi-line is true.
819                 /// </para>
820                 /// </remarks>
821                 public void BeginTextEditing()
822                 {
823
824                         if(this.Chart != null && this.AllowTextEditing)
825                         {
826                                 // Dispose previous text box
827                                 if(_editTextBox != null)
828                                 {
829                                         if(this.Chart.Controls.Contains(_editTextBox))
830                                         {
831                                                 this.Chart.Controls.Remove(_editTextBox);
832                                         }
833                                         _editTextBox.Dispose();
834                                         _editTextBox = null;
835                                 }
836
837                                 // Create a text box inside the chart
838                                 _editTextBox = new TextBox();
839                                 _editTextBox.Text = this.Text;
840                                 _editTextBox.Multiline = this.IsMultiline;
841                                 _editTextBox.Font = this.Font;
842                                 _editTextBox.BorderStyle = BorderStyle.FixedSingle;
843                                 _editTextBox.BackColor = Color.FromArgb(255, (this.BackColor.IsEmpty) ? Color.White : this.BackColor);
844                                 _editTextBox.ForeColor = Color.FromArgb(255, this.ForeColor);
845
846                                 // Calculate text position in relative coordinates
847                                 PointF firstPoint = PointF.Empty;
848                                 PointF anchorPoint = PointF.Empty;
849                                 SizeF size = SizeF.Empty;
850                                 GetRelativePosition(out firstPoint, out size, out anchorPoint);
851                                 PointF  secondPoint = new PointF(firstPoint.X + size.Width, firstPoint.Y + size.Height);
852                                 RectangleF textPosition = new RectangleF(firstPoint, new SizeF(secondPoint.X - firstPoint.X, secondPoint.Y - firstPoint.Y));
853                                 if(textPosition.Width < 0)
854                                 {
855                                         textPosition.X = textPosition.Right;
856                                         textPosition.Width = -textPosition.Width;
857                                 }
858                                 if(textPosition.Height < 0)
859                                 {
860                                         textPosition.Y = textPosition.Bottom;
861                                         textPosition.Height = -textPosition.Height;
862                                 }
863
864                                 // Set text control position in pixels
865                                 if(GetGraphics() != null)
866                                 {
867                                         // Convert point to relative coordinates
868                                         textPosition = GetGraphics().GetAbsoluteRectangle(textPosition);
869                                 }
870
871                                 // Adjust Location and Size
872                                 if(this.IsMultiline)
873                                 {
874                                         textPosition.X -= 1;
875                                         textPosition.Y -= 1;
876                                         textPosition.Width += 2;
877                                         textPosition.Height += 2;
878                                 }
879                                 else
880                                 {
881                                         textPosition.Y += textPosition.Height / 2f - _editTextBox.Size.Height / 2f;
882                                 }
883                 _editTextBox.Location = Point.Round(textPosition.Location);
884                                 _editTextBox.Size = Size.Round(textPosition.Size);
885
886                                 // Add control to the chart
887                                 this.Chart.Controls.Add(_editTextBox);
888                                 try
889                                 {
890                                         _editTextBox.SelectAll();
891                                         _editTextBox.Focus();
892                                 }
893                                 catch(SecurityException)
894                                 {
895                                         // Ignore security issues
896                                 }
897
898                                 try
899                                 {
900                                         // Set text box event hanlers
901                                         _editTextBox.KeyDown += new KeyEventHandler(OnTextBoxKeyDown);
902                                         _editTextBox.LostFocus += new EventHandler(OnTextBoxLostFocus);
903                                 }
904                                 catch(SecurityException)
905                                 {
906                                         // Ignore security issues
907                                 }
908                         }
909                 }
910
911 #endif // Microsoft_CONTROL
912
913                 #endregion      // Text Editing
914
915                 #region Content Size
916
917                 /// <summary>
918                 /// Gets text annotation content size based on the text and font.
919                 /// </summary>
920                 /// <returns>Annotation content position.</returns>
921                 override internal RectangleF GetContentPosition()
922                 {
923                         // Return pre calculated value
924                         if(!contentSize.IsEmpty)
925                         {
926                                 return new RectangleF(float.NaN, float.NaN, contentSize.Width, contentSize.Height);
927                         }
928
929                         // Create temporary bitmap based chart graphics if chart was not 
930                         // rendered yet and the graphics was not created.
931                         // NOTE: Fix for issue #3978.
932                         Graphics                graphics = null;
933 System.Drawing.Image            graphicsImage = null;
934                         ChartGraphics   tempChartGraph = null;
935                         if(GetGraphics() == null &&     this.Common != null)
936                         {
937                 graphicsImage = new System.Drawing.Bitmap(Common.ChartPicture.Width, Common.ChartPicture.Height);
938                                 graphics = Graphics.FromImage( graphicsImage );
939                                 tempChartGraph = new ChartGraphics( Common );
940                                 tempChartGraph.Graphics = graphics;
941                                 tempChartGraph.SetPictureSize( Common.ChartPicture.Width, Common.ChartPicture.Height );
942                                 this.Common.graph = tempChartGraph;
943                         }
944
945                         // Calculate content size
946                         RectangleF result = RectangleF.Empty;
947                         if(GetGraphics() != null && this.Text.Trim().Length > 0)
948                         {
949                                 // Measure text using current font and slightly increase it
950                 contentSize = GetGraphics().MeasureString(
951                      "W" + this.ReplaceKeywords(this.Text.Replace("\\n", "\n")),
952                      this.Font,
953                      new SizeF(2000, 2000),
954                      StringFormat.GenericTypographic);
955
956                                 contentSize.Height *= 1.04f;
957
958                                 // Convert to relative coordinates
959                                 contentSize = GetGraphics().GetRelativeSize(contentSize);
960
961                                 // Add spacing
962                                 bool annotationRelative = false;
963                                 RectangleF      textSpacing = GetTextSpacing(out annotationRelative);
964                                 float spacingScaleX = 1f;
965                                 float spacingScaleY = 1f;
966                                 if(annotationRelative)
967                                 {
968                                         if(contentSize.Width > 25f)
969                                         {
970                                                 spacingScaleX = contentSize.Width / 25f;
971                                                 spacingScaleX = Math.Max(1f, spacingScaleX);
972                                         }
973                                         if(contentSize.Height > 25f)
974                                         {
975                                                 spacingScaleY = contentSize.Height / 25f;
976                                                 spacingScaleY = Math.Max(1f, spacingScaleY);
977                                         }
978                                 }
979
980                                 contentSize.Width += (textSpacing.X + textSpacing.Width) * spacingScaleX;
981                                 contentSize.Height += (textSpacing.Y + textSpacing.Height) * spacingScaleY;
982
983                                 result = new RectangleF(float.NaN, float.NaN, contentSize.Width, contentSize.Height);
984                         }
985
986                         // Dispose temporary chart graphics
987                         if(tempChartGraph != null)
988                         {
989                                 tempChartGraph.Dispose();
990                                 graphics.Dispose();
991                                 graphicsImage.Dispose();
992                                 this.Common.graph = null;
993                         }
994
995                         return result;
996                 }
997
998                 /// <summary>
999                 /// Gets text spacing on four different sides in relative coordinates.
1000                 /// </summary>
1001                 /// <param name="annotationRelative">Indicates that spacing is in annotation relative coordinates.</param>
1002                 /// <returns>Rectangle with text spacing values.</returns>
1003                 internal virtual RectangleF GetTextSpacing(out bool annotationRelative)
1004                 {
1005                         annotationRelative = false;
1006                         RectangleF rect = new RectangleF(3f, 3f, 3f, 3f);
1007                         if(GetGraphics() != null)
1008                         {
1009                                 rect = GetGraphics().GetRelativeRectangle(rect);
1010                         }
1011                         return rect;
1012                 }
1013
1014                 #endregion
1015
1016                 #region Placement Methods
1017
1018 #if Microsoft_CONTROL
1019
1020                 /// <summary>
1021                 /// Ends user placement of an annotation.
1022                 /// </summary>
1023                 /// <remarks>
1024                 /// Ends an annotation placement operation previously started by a 
1025                 /// <see cref="Annotation.BeginPlacement"/> method call.
1026                 /// <para>
1027                 /// Calling this method is not required, since placement will automatically
1028                 /// end when an end user enters all required points. However, it is useful when an annotation 
1029                 /// placement operation needs to be aborted for some reason.
1030                 /// </para>
1031                 /// </remarks>
1032                 override public void EndPlacement()
1033                 {
1034                         // Check if text editing is allowed
1035                         // Maybe changed later in the EndPlacement method.
1036                         bool allowTextEditing = this.AllowTextEditing;
1037
1038                         // Call base class
1039                         base.EndPlacement();
1040
1041                         // Begin text editing
1042                         if(this.Chart != null)
1043                         {
1044                                 this.Chart.Annotations.lastClickedAnnotation = this;
1045                                 if(allowTextEditing)
1046                                 {
1047                                         BeginTextEditing();
1048                                 }
1049                         }
1050                 }
1051
1052 #endif // Microsoft_CONTROL
1053
1054         #endregion // Placement Methods
1055
1056         #endregion      // Methods
1057     }
1058
1059         /// <summary>
1060         /// The <b>AnnotationSmartLabelStyle</b> class is used to store an annotation's smart 
1061         /// labels properties.
1062         /// <seealso cref="Annotation.SmartLabelStyle"/>
1063         /// </summary>
1064         /// <remarks>
1065         /// This class is derived from the <b>SmartLabelStyle</b> class
1066         /// used for <b>Series</b> objects.
1067         /// </remarks>
1068         [
1069                 DefaultProperty("Enabled"),
1070                 SRDescription("DescriptionAttributeAnnotationSmartLabelsStyle_AnnotationSmartLabelsStyle"),
1071                 TypeConverter(typeof(NoNameExpandableObjectConverter)),
1072         ]
1073 #if ASPPERM_35
1074         [AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
1075     [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
1076 #endif
1077     public class AnnotationSmartLabelStyle : SmartLabelStyle
1078         {
1079                 #region Constructors and initialization
1080
1081                 /// <summary>
1082                 /// Default public constructor.
1083                 /// </summary>
1084                 public AnnotationSmartLabelStyle()
1085                 {
1086                         this.chartElement = null;
1087                 }
1088
1089                 /// <summary>
1090                 /// Constructor.
1091                 /// </summary>
1092                 /// <param name="chartElement">
1093                 /// Chart element this style belongs to.
1094                 /// </param>
1095                 public AnnotationSmartLabelStyle(Object chartElement) : base(chartElement)
1096                 {
1097                 }
1098
1099                 #endregion
1100
1101                 #region Non Applicable Appearance Attributes (set as Non-Browsable)
1102
1103
1104                 /// <summary>
1105                 /// Callout style of the repositioned smart labels.
1106                 /// </summary>
1107                 /// <remarks>
1108                 /// This method is for internal use and is hidden at design time and runtime.
1109                 /// </remarks>
1110                 [
1111                 SRCategory("CategoryAttributeMisc"),
1112                 Browsable(false),
1113                 EditorBrowsableAttribute(EditorBrowsableState.Never),
1114                 DefaultValue(LabelCalloutStyle.Underlined),
1115                 SRDescription("DescriptionAttributeCalloutStyle3"),
1116                 ]
1117                 override public LabelCalloutStyle CalloutStyle
1118                 {
1119                         get
1120                         {
1121                                 return base.CalloutStyle;
1122                         }
1123                         set
1124                         {
1125                                 base.CalloutStyle = value;
1126                         }
1127                 }
1128
1129                 /// <summary>
1130                 /// Label callout line color.
1131                 /// </summary>
1132                 /// <remarks>
1133         /// This method is for internal use and is hidden at design and run time.
1134                 /// </remarks>
1135                 [
1136                 SRCategory("CategoryAttributeAppearance"),
1137                 Browsable(false),
1138                 EditorBrowsableAttribute(EditorBrowsableState.Never),
1139                 DefaultValue(typeof(Color), "Black"),
1140         SRDescription("DescriptionAttributeCalloutLineColor"),
1141         TypeConverter(typeof(ColorConverter)),
1142         Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base)
1143                 ]
1144                 override public Color CalloutLineColor
1145                 {
1146                         get
1147                         {
1148                                 return base.CalloutLineColor;
1149                         }
1150                         set
1151                         {
1152                                 base.CalloutLineColor = value;
1153                         }
1154                 }
1155
1156                 /// <summary>
1157                 /// Label callout line style.
1158                 /// </summary>
1159                 /// <remarks>
1160         /// This method is for internal use and is hidden at design and run time.
1161                 /// </remarks>
1162                 [
1163                 SRCategory("CategoryAttributeAppearance"),
1164                 Browsable(false),
1165                 EditorBrowsableAttribute(EditorBrowsableState.Never),
1166                 DefaultValue(ChartDashStyle.Solid),
1167         SRDescription("DescriptionAttributeLineDashStyle"),
1168                         #if !Microsoft_CONTROL
1169                         PersistenceMode(PersistenceMode.Attribute)
1170                         #endif
1171                 ]
1172                 override public ChartDashStyle CalloutLineDashStyle
1173                 {
1174                         get
1175                         {
1176                                 return base.CalloutLineDashStyle;
1177                         }
1178                         set
1179                         {
1180                                 base.CalloutLineDashStyle = value;
1181                         }
1182                 }
1183
1184                 /// <summary>
1185                 /// Label callout back color. Applies to the Box style only.
1186                 /// </summary>
1187                 /// <remarks>
1188         /// This method is for internal use and is hidden at design and run time.
1189                 /// </remarks>
1190                 [
1191                 SRCategory("CategoryAttributeAppearance"),
1192                 Browsable(false),
1193                 EditorBrowsableAttribute(EditorBrowsableState.Never),
1194                 DefaultValue(typeof(Color), "Transparent"),
1195         SRDescription("DescriptionAttributeCalloutBackColor"),
1196         TypeConverter(typeof(ColorConverter)),
1197         Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base)
1198                 ]
1199                 override public Color CalloutBackColor
1200                 {
1201                         get
1202                         {
1203                                 return base.CalloutBackColor;
1204                         }
1205                         set
1206                         {
1207                                 base.CalloutBackColor = value;
1208                         }
1209                 }
1210
1211                 /// <summary>
1212                 /// Label callout line width.
1213                 /// </summary>
1214                 /// <remarks>
1215         /// This method is for internal use and is hidden at design and run time.
1216                 /// </remarks>
1217                 [
1218                 SRCategory("CategoryAttributeAppearance"),
1219                 Browsable(false),
1220                 EditorBrowsableAttribute(EditorBrowsableState.Never),
1221                 DefaultValue(1),
1222         SRDescription("DescriptionAttributeLineWidth"),
1223                 ]
1224                 override public int CalloutLineWidth
1225                 {
1226                         get
1227                         {
1228                                 return base.CalloutLineWidth;
1229                         }
1230                         set
1231                         {
1232                                 base.CalloutLineWidth = value;
1233                         }
1234                 }
1235
1236                 /// <summary>
1237                 /// Label callout line anchor cap.
1238                 /// </summary>
1239                 /// <remarks>
1240         /// This method is for internal use and is hidden at design and run time.
1241                 /// </remarks>
1242                 [
1243                 SRCategory("CategoryAttributeAppearance"),
1244                 Browsable(false),
1245                 EditorBrowsableAttribute(EditorBrowsableState.Never),
1246                 DefaultValue(LineAnchorCapStyle.Arrow),
1247                 SRDescription("DescriptionAttributeCalloutLineAnchorCapStyle"),
1248                 ]
1249                 override public LineAnchorCapStyle CalloutLineAnchorCapStyle
1250                 {
1251                         get
1252                         {
1253                                 return base.CalloutLineAnchorCapStyle;
1254                         }
1255                         set
1256                         {
1257                                 base.CalloutLineAnchorCapStyle = value;
1258                         }
1259                 }
1260
1261                 #endregion 
1262         }
1263 }