예제 #1
0
파일: D2dBitmap.cs 프로젝트: Gfour84/ATF
 internal D2dBitmap(D2dGraphics owner, SharpDX.Direct2D1.Bitmap bmp)
 {            
     m_nativeBitmap = bmp;
     m_owner = owner;
     m_bitmap = null;
     m_owner.RecreateResources += RecreateResources;
     m_rtNumber = owner.RenderTargetNumber;
 }
예제 #2
0
파일: D2dBitmap.cs 프로젝트: Gfour84/ATF
        internal D2dBitmap(D2dGraphics owner, System.Drawing.Bitmap bmp)
        {
            if (bmp.PixelFormat != GdiPixelFormat.Format32bppPArgb)
                throw new System.ArgumentException("pixel format must be GdiPixelFormat.Format32bppPArgb");                

            m_owner = owner;
            m_bitmap = bmp;
            Create();
            m_owner.RecreateResources += RecreateResources;
            m_rtNumber = owner.RenderTargetNumber;
        }
 internal D2dRadialGradientBrush(D2dGraphics owner, PointF center,
     PointF gradientOriginOffset,
     float radiusX,
     float radiusY,
     params D2dGradientStop[] gradientStops)
     : base(owner)
 {
     m_center = center;
     m_gradientOriginOffset = gradientOriginOffset;
     m_radiusX = radiusX;
     m_radiusY = radiusY;            
     m_gradientStops = new D2dGradientStop[gradientStops.Length];
     Array.Copy(gradientStops, m_gradientStops, m_gradientStops.Length);
     Create();//to-do: it's dangerous to call a virtual method in a constructor; derived class may not be properly initialized!
 }
        /// <summary>
        /// Initializes class with graphics object</summary>
        /// <param name="graphics">Graphics object for drawing</param>
        public override void Init(D2dGraphics graphics)
        {
            base.Init(graphics);

            SelectedBrush = graphics.CreateSolidBrush(Color.Tomato);//should have width of 3
            CollapsedBrush = graphics.CreateSolidBrush(Color.LightGray);
            InvalidBrush = graphics.CreateSolidBrush(Color.DimGray);
            GroupBrush = graphics.CreateLinearGradientBrush(
                new D2dGradientStop(Color.LightGoldenrodYellow, 0),
                new D2dGradientStop(Color.Khaki, 1));
            GhostGroupBrush = graphics.CreateSolidBrush(Color.FromArgb(128, Color.Gray));
            TrackBrush = graphics.CreateSolidBrush(Color.LightGray);
            GhostTrackBrush = graphics.CreateSolidBrush(Color.FromArgb(128, Color.Gray));
            TextBrush = graphics.CreateSolidBrush(SystemColors.WindowText);
        }
예제 #5
0
        internal D2dLinearGradientBrush(D2dGraphics owner, PointF pt1,
            PointF pt2,
            D2dGradientStop[] gradientStops,
            D2dExtendMode extendMode,
            D2dGamma gamma)
            : base(owner)
        {
            m_start = pt1;
            m_end = pt2;            
            m_gradientStops = new D2dGradientStop[gradientStops.Length];
            Array.Copy(gradientStops, m_gradientStops, m_gradientStops.Length);

            m_gamma = gamma;
            m_extendMode = extendMode;
            Create();//to-do: it's dangerous to call a virtual method in a constructor; derived class may not be properly initialized!
        }
예제 #6
0
 /// <summary>
 /// Initializes this class with a graphics object. Must be called before using this class to render.</summary>
 /// <param name="graphics">The graphics object that this TimelineRenderer will permanently use</param>
 public virtual void Init(D2dGraphics graphics)
 {
     if (m_graphics != null)
         throw new InvalidOperationException("Only call Init() once");
     m_graphics = graphics;
     m_gridPen = m_graphics.CreateSolidBrush(Color.FromArgb(128, 128, 128, 128));
     m_headerBrush = m_graphics.CreateSolidBrush(SystemColors.Control);
     m_headerLineBrush = m_graphics.CreateSolidBrush(SystemColors.ControlDark);
     m_scaleLineBrush = m_graphics.CreateSolidBrush(SystemColors.ControlDark);
     m_expanderBrush = m_graphics.CreateSolidBrush(Color.DimGray);
     m_nameBrush = m_graphics.CreateSolidBrush(SystemColors.WindowText);
     m_scaleTextBrush = m_graphics.CreateSolidBrush(SystemColors.WindowText);
     m_generalSolidColorBrush = m_graphics.CreateSolidBrush(Color.Empty);
     
     m_trackTextFormat = D2dFactory.CreateTextFormat(Font);
     m_trackTextFormat.ParagraphAlignment = D2dParagraphAlignment.Far;
     m_trackTextFormat.TextAlignment = D2dTextAlignment.Trailing;
 }
예제 #7
0
        /// <summary>
        /// Draws horizontal grid using Direct2D</summary>
        /// <param name="transform">Transform from graph (world) to Window's client (screen) transform</param>
        /// <param name="graphRect">Graph rectangle</param>
        /// <param name="step">Grid step in canvas coordinates</param>
        /// <param name="color">Grid line color</param>
        /// <param name="g">Graphics Direct2D drawing surface</param>
        public static void DrawHorizontalGrid(
          Matrix transform,
          RectangleF graphRect,
          double step,
          Color color,
          D2dGraphics g)
        {
            double yScale = transform.Elements[3];
            RectangleF clientRect = GdiUtil.Transform(transform, graphRect);

            double screenStep = Math.Abs(yScale * step);

            int a  = ComputeOpacity(screenStep);
            color = Color.FromArgb(a, color);                            
            double start = graphRect.Top - MathUtil.Remainder(graphRect.Top, step) + step;
            for (double y = start; y < graphRect.Bottom; y += step)
            {
                double cy = (y - graphRect.Top) * yScale + clientRect.Top;
                g.DrawLine(clientRect.Left, (float)cy, clientRect.Right, (float)cy, color);
            }            
        }
예제 #8
0
        /// <summary>
        /// Draws the scrubber manipulator and calculates the bounding rectangle on the handle</summary>
        /// <param name="g">The graphics object to draw with</param>
        /// <param name="handleRect">The handle's bounding rectangle for pick tests, in view
        /// coordinates</param>
        protected virtual void DrawManipulator(D2dGraphics g, out RectangleF handleRect)
        {
            Matrix worldToView = Owner.Transform;
            float viewX = Sce.Atf.GdiUtil.Transform(worldToView, Position);
            Rectangle clipRectangle = Owner.VisibleClientRectangle;

            // allow only the arrow portion to be selected
            handleRect = new RectangleF(
                viewX - 5,
                clipRectangle.Top,
                10,
                7);

            g.DrawLine(viewX, clipRectangle.Top, viewX, clipRectangle.Bottom, s_color, 1.0f, null);

            Color handle_color = m_isMoving ? Color.Tomato : s_color;
            float pos_x = viewX;
            float pos_y = clipRectangle.Top + 5;
            s_arrow[0] = new PointF(pos_x - 4, pos_y - 5);
            s_arrow[1] = new PointF(pos_x - 4, pos_y);
            s_arrow[2] = new PointF(pos_x - 5, pos_y + 1);
            s_arrow[3] = new PointF(pos_x - 5, pos_y + 2);
            s_arrow[4] = new PointF(pos_x, pos_y + 7);
            s_arrow[5] = new PointF(pos_x + 5, pos_y + 2);
            s_arrow[6] = new PointF(pos_x + 5, pos_y + 1);
            s_arrow[7] = new PointF(pos_x + 4, pos_y);
            s_arrow[8] = new PointF(pos_x + 4, pos_y - 5);
            //g.FillPolygon(s_arrow, handle_color);   // Fill arrow
            // Draw arrow border with same gray Photoshop uses
            //g.DrawLines(s_arrow, Color.FromArgb(116, 114, 106), 3.0f);

            g.DrawLines(s_arrow, handle_color, 2.0f);

            string label = Position.ToString(CultureInfo.CurrentCulture);
            g.DrawText(label, Owner.Renderer.TextFormat, new PointF(pos_x + 6, clipRectangle.Top), SystemColors.WindowText);
        }
예제 #9
0
파일: D2dBitmap.cs 프로젝트: sbambach/ATF
        internal D2dBitmap(D2dGraphics owner, int width, int height)
        {
            if (width < 1 || height < 1)
                throw new ArgumentOutOfRangeException("Width and height must be greater than zero");

            m_owner = owner;
            var props = new SharpDX.Direct2D1.BitmapProperties();
            props.DpiX = m_owner.DotsPerInch.Width;
            props.DpiY = m_owner.DotsPerInch.Height;
            props.PixelFormat = new SharpDX.Direct2D1.PixelFormat(SharpDX.DXGI.Format.B8G8R8A8_UNorm, SharpDX.Direct2D1.AlphaMode.Premultiplied);
            m_nativeBitmap = new SharpDX.Direct2D1.Bitmap(m_owner.D2dRenderTarget, new Size2(width, height), props);
            m_owner.RecreateResources += RecreateResources;
            m_rtNumber = owner.RenderTargetNumber;
        }
예제 #10
0
            /// <summary>
            /// Constructor</summary>
            /// <param name="renderer">Timeline renderer</param>
            /// <param name="transform">Transform, taking timeline coordinates to display</param>
            /// <param name="clientRectangle">Bounds of displayed area of timeline, in screen space</param>
            /// <param name="g">Graphics object</param>
            public Context(
                D2dTimelineRenderer renderer,
                Matrix transform,
                RectangleF clientRectangle,
                D2dGraphics g)
            {
                Graphics = g;

                Transform = transform;

                ClientRectangle = clientRectangle;
                Bounds = GdiUtil.InverseTransform(transform, clientRectangle);

                TextFormat = renderer.m_textFormat;
                FontHeight = renderer.m_textFormat.FontHeight;

                PixelSize = new SizeF(1 / transform.Elements[0], 1 / transform.Elements[3]);
            }
예제 #11
0
        private void DrawAnnotation(IAnnotation annotation, DiagramDrawingStyle style, D2dGraphics g, bool drawText, RectangleF graphBound)
        {
            // fill background
            Rectangle bounds = annotation.Bounds;

            Color backColor = m_coloringContext == null
                                  ? SystemColors.Info
                                  : (Color) m_coloringContext.GetColor(ColoringTypes.BackColor, annotation);
            // keep the width of border in 1 pixel after transformation to avoid D2d antialiasing away the line
            float borderThickness = 1.0f/m_scaleX;
            g.FillRectangle(bounds, backColor);
            g.DrawRectangle(bounds, ControlPaint.Dark(backColor), borderThickness, null);
       
            // draw titlebar
            if (style == DiagramDrawingStyle.LastSelected || style == DiagramDrawingStyle.Selected)
            {
                var titleBarRect = new RectangleF(bounds.X, bounds.Y, bounds.Width, Margin.Top - 1);
                g.FillRectangle(titleBarRect, ControlPaint.Dark(backColor));
            }
            // line seperate titlebar from text content     
            g.DrawLine(bounds.X, bounds.Y + Margin.Top-1, bounds.X + bounds.Width, bounds.Y + Margin.Top-1, ControlPaint.Dark(backColor), borderThickness);

            // draw content
            if (drawText)
            {
                var contentBounds = new RectangleF(bounds.X + Margin.Left, bounds.Y + Margin.Top,
                                               bounds.Width - Margin.Size.Width, bounds.Height - Margin.Size.Height);

                contentBounds.Width = Math.Max(contentBounds.Width, MinimumWidth);
                contentBounds.Height = Math.Max(contentBounds.Height, MinimumHeight);
                var textBounds = contentBounds;              
    
                int topLine = 0;
                D2dTextLayout textLayout = null;

                if (m_annotationEditors.ContainsKey(annotation))
                {
                                     
                    var annotationEditor = m_annotationEditors[annotation];
                    if (annotationEditor.TextLayout.Text != annotation.Text) // text content changed, for example, undo,redo
                    {
                        annotationEditor.ResetText(annotation.Text);
                    }
                    topLine = annotationEditor.TopLine;
                    textLayout = m_annotationEditors[annotation].TextLayout;
                    annotationEditor.VerticalScrollBarVisibe = textLayout.Height > textLayout.LayoutHeight;

                    if (m_annotationEditors[annotation].VerticalScrollBarVisibe)
                        textBounds.Width -= ScrollBarWidth + 2 * ScrollBarMargin;
                    textLayout.LayoutWidth = textBounds.Width;
                    textLayout.LayoutHeight = textBounds.Height;
                 
                }

                if (textLayout == null)
                {
                    // first assume no v-scroll bar needed
                    textLayout = D2dFactory.CreateTextLayout(annotation.Text, m_theme.TextFormat, contentBounds.Width, contentBounds.Height);
                    if (m_theme.TextFormat.Underlined)
                        textLayout.SetUnderline(true, 0, annotation.Text.Length);
                    if (m_theme.TextFormat.Strikeout)
                        textLayout.SetStrikethrough(true, 0, annotation.Text.Length);

                    if (textLayout.Height >  textLayout.LayoutHeight) // need v-scroll bar
                    {
                        textLayout.LayoutWidth = contentBounds.Width - ScrollBarWidth - 2*ScrollBarMargin;
                      
                    }
                    m_annotationEditors.Add(annotation, new TextEditor()
                        {
                            TextLayout = textLayout,
                            TextFormat = m_theme.TextFormat,
                            TopLine =  topLine,
                            VerticalScrollBarVisibe = textLayout.Height > textLayout.LayoutHeight
                        });
                }

                var annotationData = m_annotationEditors[annotation];
                PointF origin = new PointF(contentBounds.Location.X, contentBounds.Location.Y - topLine *  m_theme.TextFormat.FontHeight);

                g.PushAxisAlignedClip(contentBounds);

                // draw the selection range behind the text.
                if (annotationData.SelectionLength > 0)
                {
                    var hitTestMetrics = textLayout.HitTestTextRange(annotationData.SelectionStart, annotationData.SelectionLength, 0, 0);
                    for (int i = 0; i < hitTestMetrics.Length; ++i)
                    {

                        var highlightRect = new RectangleF(hitTestMetrics[i].Point.X, hitTestMetrics[i].Point.Y, hitTestMetrics[i].Width,
                                                           hitTestMetrics[i].Height);
                        highlightRect.Offset(origin);
                        g.FillRectangle(highlightRect, m_theme.TextHighlightBrush);
                    }               
                }

                // draw caret
                
                if ( style == DiagramDrawingStyle.Selected || style == DiagramDrawingStyle.LastSelected)
                {
                    textLayout = annotationData.TextLayout;
                    var caretRect = m_annotationEditors[annotation].GetCaretRect();
                    caretRect.Offset(origin);
                    //g.FillRectangle(caretRect, m_theme.HotBrush);

                    // set Windows caret position                  
                    if (m_editingText && contentBounds.IntersectsWith(caretRect) && graphBound.IntersectsWith(caretRect) && AdaptedControl.Focused)
                    {
                        var caretClientRect = GdiUtil.Transform(m_transformAdapter.Transform, caretRect);
                        float ratio = m_scaleX*m_theme.TextFormat.FontHeight/CaretHeight;                      
                        if (ratio > 1.1f || ratio < 0.9f) // adjust caret height
                        {
                            CaretHeight = (int)(m_scaleX*m_theme.TextFormat.FontHeight);
                            User32.DestroyCaret();
                            User32.CreateCaret(AdaptedControl.Handle, IntPtr.Zero, CaretWidth, CaretHeight);
                        }
                        // align bottom    
                        User32.SetCaretPos((int) caretClientRect.X, (int)(caretClientRect.Y + caretClientRect.Height - CaretHeight));
                        if (!m_rmbPressed)
                            AdaptedControl.HasKeyboardFocus = true;
                    }
                    else
                        HideCaret();
                }

                // draw text 
                g.DrawTextLayout(origin, textLayout, m_theme.TextBrush); 

                g.PopAxisAlignedClip();

                // draw v-scroll bar
                if (contentBounds.Height < textLayout.Height)
                {
                    float visibleLines = contentBounds.Height / m_theme.TextFormat.FontHeight;
                    float vMin = topLine * textLayout.LayoutHeight / textLayout.LineCount;
                    float vMax = (topLine + visibleLines-1) * textLayout.LayoutHeight / textLayout.LineCount;
                    if (m_scrolling)
                    {
                        var trackBounds = new RectangleF(contentBounds.Right - ScrollBarMargin - ScrollBarWidth, contentBounds.Y, ScrollBarWidth, contentBounds.Height);
                        g.FillRectangle(trackBounds, Color.Gainsboro);                    
                    }
                    var thumbBounds = new RectangleF(contentBounds.Right - ScrollBarMargin - ScrollBarWidth, contentBounds.Y + vMin, ScrollBarWidth, vMax - vMin);
                    g.FillRectangle(thumbBounds, Color.DimGray);
                }                
            }
            else
                HideCaret();
        }
예제 #12
0
        internal D2dBitmapBrush(D2dGraphics owner, D2dBitmap bitmap)
            : base(owner)
        {
            m_bitmap = bitmap;

            m_extendModeX = D2dExtendMode.Clamp;
            m_extendModeY = D2dExtendMode.Clamp;
            m_location = new PointF(1, 1);
            m_interpolationMode = D2dBitmapInterpolationMode.Linear;
            Create();//to-do: it's dangerous to call a virtual method in a constructor; derived class may not be properly initialized!
        }
예제 #13
0
 internal D2dSolidColorBrush(D2dGraphics owner, Color color)
     : base(owner)
 {
     m_color = color;
     Create();//to-do: it's dangerous to call a virtual method in a constructor; derived class may not be properly initialized!
 }
예제 #14
0
파일: D2dUtil.cs 프로젝트: Joxx0r/ATF
 /// <summary>
 /// Draws a pin button, which looks like a square with
 /// a dash (expanded) or a cross (unexpanded).</summary>
 /// <param name="x">X coordinate of pin top left corner</param>
 /// <param name="y">Y coordinate of pin top left corner</param>
 /// <param name="pinned">Whether or not pin should appear "pinned"</param>
 /// <param name="toLeft">Whether pin points left or right</param>
 /// <param name="pen">Pen, should be 1 pixel wide</param>
 /// <param name="g">Graphics object</param>
 public static void DrawPin(int x, int y, bool pinned, bool toLeft, D2dBrush pen, D2dGraphics g)
 {
     if (toLeft)
         DrawLeftPin(x, y, ThumbtackSize, pen, pinned, g);
     else
         DrawRightPin(x, y, ThumbtackSize, pen, pinned, g);
 }
예제 #15
0
 internal D2dBrush(D2dGraphics owner)
 {
     m_owner = owner;
     m_owner.RecreateResources += RecreateResources;
     m_rtNumber = owner.RenderTargetNumber;
 }
예제 #16
0
 internal D2dBitmapGraphics(D2dGraphics owner,BitmapRenderTarget renderTarget)
     : base(renderTarget)
 {
     m_owner = owner;
 }
예제 #17
0
        /// <summary>
        /// Draws vertical grid lines using Direct2D</summary>
        /// <param name="transform">Transform from graph (world) to Window's client (screen) transform</param>
        /// <param name="graphRect">Graph rectangle</param>
        /// <param name="step">Grid step in canvas coordinates</param>
        /// <param name="color">Grid line color</param>
        /// <param name="g">Graphics Direct2D drawing surface</param>
        public static void DrawVerticalGrid(
            Matrix transform,
            RectangleF graphRect,
            double step,
            Color color,
            D2dGraphics g)
        {
            double xScale = transform.Elements[0];
            RectangleF clientRect = GdiUtil.Transform(transform, graphRect);

            double screenStep = Math.Abs(xScale * step);
            int a  = ComputeOpacity(screenStep);
            color = Color.FromArgb(a, color);

            double start = graphRect.Left - MathUtil.Remainder(graphRect.Left, step) + step;
            for (double x = start; x < graphRect.Right; x += step)
            {
                double cx = (x - graphRect.Left) * xScale + clientRect.Left;
                g.DrawLine((float)cx, clientRect.Top, (float)cx, clientRect.Bottom, color);
            }            
        }
예제 #18
0
파일: D2dUtil.cs 프로젝트: Joxx0r/ATF
        /// <summary>
        /// Draws a tree-control style expander, which looks like a square with
        /// a dash (expanded) or a cross (unexpanded).</summary>
        /// <param name="x">X coordinate of expander top right corner</param>
        /// <param name="y">Y coordinate of expander top right corner</param>
        /// <param name="pen">Pen, should be 1 pixel wide</param>
        /// <param name="size">Size of pin, in pixels</param>
        /// <param name="pinned">Whether or not expander should appear "expanded"</param>
        /// <param name="g">Graphics object</param>
        public static void DrawRightPin(int x, int y, int size, D2dBrush pen, bool pinned, D2dGraphics g)
        {
            //g.DrawRectangle(pen, x - size, y, size, size);

            int rectWidth = size / 4;
            int rectHeight = 2 * size / 3;
            int center = size / 2;
            if (pinned)
            {
                g.DrawLine(x + center - size, y + rectHeight, x + center - size, y + size, pen); //lower center-vertical line
                g.DrawLine(x - size, y + rectHeight, x, y + rectHeight, pen); // middle-horizontal line
                g.DrawRectangle(new RectangleF(x + rectWidth - size, y, 2 * rectWidth, rectHeight), pen);
                //g.DrawLine(pen, x + 3 * rectWidth - 1, y, x + 3 * rectWidth - 1, y + rectHeight); // a vertial line next to the right side of the rect
                g.DrawLine(x + 3 * rectWidth - 1 - size, y,
                               x + 3 * rectWidth - 1 - size, y + rectHeight, pen); // a vertial line next to the right side of the rect

            }
            else
            {
                g.DrawLine(x, y + center, x - size + rectHeight, y + center, pen); //left center-horizontal line
                g.DrawLine(x - size + rectHeight, y, x - size + rectHeight, y + size, pen); // middle-vertical line
                g.DrawRectangle(new RectangleF(x - size, y + (size - rectWidth) / 2 - 1, rectHeight, 2 * rectWidth), pen);
                g.DrawLine(x - size + rectHeight, y + (size - rectWidth) / 2 + 2 * rectWidth - 2, x - size, y + (size - rectWidth) / 2 + 2 * rectWidth - 2, pen); // a horizontal line next to the bottom side of the rect

            }

        }
예제 #19
0
        private void DrawAnnotation(IAnnotation annotation, DiagramDrawingStyle style, D2dGraphics g, bool drawText, RectangleF graphBound)
        {
            // fill background
            Rectangle bounds = annotation.Bounds;

            Color backColor = m_coloringContext == null
                                  ? SystemColors.Info
                                  : m_coloringContext.GetColor(ColoringTypes.BackColor, annotation);
            Color foreColor = m_coloringContext == null
                        ? SystemColors.WindowText
                        : m_coloringContext.GetColor(ColoringTypes.ForeColor, annotation);

            // keep the width of border in 2 pixel after transformation to avoid D2d antialiasing away the line
            float borderThickness = 2.0f/m_scaleX;
            g.FillRectangle(bounds, backColor);

            g.DrawRectangle(bounds, m_theme.GetOutLineBrush(style), borderThickness);
       
            //// draw titlebar
            //if (style == DiagramDrawingStyle.LastSelected || style == DiagramDrawingStyle.Selected)
            //{
            //    var titleBarRect = new RectangleF(bounds.X, bounds.Y, bounds.Width, Margin.Top - 1);
            //    g.FillRectangle(titleBarRect, ControlPaint.Dark(backColor));
            //}
            //// line seperate titlebar from text content     
            //g.DrawLine(bounds.X, bounds.Y + Margin.Top-1, bounds.X + bounds.Width, bounds.Y + Margin.Top-1, ControlPaint.Dark(backColor), borderThickness);
            
            // draw content
            if (drawText)
            {
                var contentBounds = new RectangleF(bounds.X + Margin.Left, bounds.Y + Margin.Top,
                                               bounds.Width - Margin.Size.Width, bounds.Height - Margin.Size.Height);
                contentBounds.Width = Math.Max(contentBounds.Width, MinimumWidth);
                contentBounds.Height = Math.Max(contentBounds.Height, MinimumHeight);
                var textBounds = contentBounds;
                
                TextEditor textEditor;
                if (!m_annotationEditors.TryGetValue(annotation,out textEditor))
                {
                    // first assume no v-scroll bar needed
                    var textLayout = D2dFactory.CreateTextLayout(annotation.Text, m_theme.TextFormat, contentBounds.Width, contentBounds.Height);
                    if (m_theme.TextFormat.Underlined)
                        textLayout.SetUnderline(true, 0, annotation.Text.Length);
                    if (m_theme.TextFormat.Strikeout)
                        textLayout.SetStrikethrough(true, 0, annotation.Text.Length);

                    if (textLayout.Height >  textLayout.LayoutHeight) // need v-scroll bar
                    {
                        textLayout.LayoutWidth = contentBounds.Width - ScrollBarWidth - 2 * ScrollBarMargin;
                      
                    }

                    textEditor = new TextEditor
                    {
                        TextLayout = textLayout,
                        TextFormat = m_theme.TextFormat,
                        TopLine =  0,
                        VerticalScrollBarVisibe = textLayout.Height > textLayout.LayoutHeight
                    };
                    m_annotationEditors.Add(annotation, textEditor);                        
                }
                else if (textEditor.TextLayout.Text != annotation.Text) // text content changed, for example, undo,redo
                {                
                    textEditor.ResetText(annotation.Text);                    
                }

                int topLine = textEditor.TopLine;
                textEditor.VerticalScrollBarVisibe = textEditor.TextLayout.Height > textEditor.TextLayout.LayoutHeight;

                if (textEditor.VerticalScrollBarVisibe)
                    textBounds.Width -= ScrollBarWidth + 2 * ScrollBarMargin;
                if (Math.Abs(textEditor.TextLayout.LayoutWidth - textBounds.Width) +
                    Math.Abs(textEditor.TextLayout.LayoutHeight - textBounds.Height) > 1.0)
                {
                    textEditor.TextLayout.LayoutWidth = textBounds.Width; // layout width and height can be updated
                    textEditor.TextLayout.LayoutHeight = textBounds.Height;
                    textEditor.Validate();
                }

                float yOffset = textEditor.GetLineYOffset(topLine);                
                PointF origin = new PointF(contentBounds.Location.X, contentBounds.Location.Y - yOffset);

                g.PushAxisAlignedClip(contentBounds);

               

                // adjust caret.
                // pull out this code to the caller.
                if ( annotation == m_editingAnnotation  && m_caretCreated)
                {                    
                    var caretRect = textEditor.GetCaretRect();
                    caretRect.Offset(origin);                   
                    // set Windows caret position                  
                    if (contentBounds.IntersectsWith(caretRect) && AdaptedControl.Focused)
                    {
                        Matrix3x2F xform = m_transformAdapter != null ? m_transformAdapter.Transform
                            : g.Transform;
                        var caretClientRect = Matrix3x2F.Transform(xform, caretRect);
                        float ratio = m_scaleX*m_theme.TextFormat.FontHeight/CaretHeight;                      
                        if (ratio > 1.1f || ratio < 0.9f) // adjust caret height
                        {
                            CaretHeight = (int)(m_scaleX*m_theme.TextFormat.FontHeight);
                            User32.DestroyCaret();
                            User32.CreateCaret(AdaptedControl.Handle, IntPtr.Zero, CaretWidth, CaretHeight);
                        }
                        // align bottom    
                        User32.SetCaretPos((int) caretClientRect.X, (int)(caretClientRect.Y + caretClientRect.Height - CaretHeight));
                        if (!m_rmbPressed)
                            AdaptedControl.HasKeyboardFocus = true;
                    }
                    else
                        HideCaret();
                }

                // draw the selection range above the text.
                if (textEditor.SelectionLength > 0)
                {
                    D2dBrush hibrush = AdaptedControl.Focused ? m_theme.TextHighlightBrush : m_solidBrush;
                    var hitTestMetrics = textEditor.TextLayout.HitTestTextRange(textEditor.SelectionStart, textEditor.SelectionLength, 0, 0);
                    for (int i = 0; i < hitTestMetrics.Length; ++i)
                    {
                        var highlightRect = new RectangleF(hitTestMetrics[i].Point.X, hitTestMetrics[i].Point.Y, hitTestMetrics[i].Width,
                                                           hitTestMetrics[i].Height);
                        highlightRect.Offset(origin);
                        g.FillRectangle(highlightRect, hibrush);
                    }
                }
                
                // draw text 
                g.DrawTextLayout(origin, textEditor.TextLayout, foreColor);

                

                g.PopAxisAlignedClip();

                // draw v-scroll bar
               // if (contentBounds.Height < textEditor.TextLayout.Height)
                if(textEditor.VerticalScrollBarVisibe)
                {
                    float visibleLines = textEditor.GetVisibleLines();
                    float vMin = topLine * contentBounds.Height / textEditor.TextLayout.LineCount;
                    float vMax = (topLine + visibleLines - 1) * contentBounds.Height / textEditor.TextLayout.LineCount;
                   // if (m_scrolling)
                   // {
                        var trackBounds = new RectangleF(contentBounds.Right - ScrollBarMargin - ScrollBarWidth, contentBounds.Y, ScrollBarWidth, contentBounds.Height);
                        g.FillRectangle(trackBounds, Color.Gainsboro);                    
                   // }
                    var thumbBounds = new RectangleF(contentBounds.Right - ScrollBarMargin - ScrollBarWidth, contentBounds.Y + vMin, ScrollBarWidth, vMax - vMin);
                    g.FillRectangle(thumbBounds, Color.DimGray);
                }                
            }                
        }