InkCanvasSelectionAdorner.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / MS / Internal / Controls / InkCanvasSelectionAdorner.cs / 1 / InkCanvasSelectionAdorner.cs

                            //---------------------------------------------------------------------------- 
//
// File: InkCanvasSelectionAdorner.cs
//
// Description: 
//      A class which is used as the selection adorner of the InkCanvas selection
// 
// Features: 
//
// History: 
//  1/27/2005 [....]:       Created
//
// Copyright (C) 2001 by Microsoft Corporation.  All rights reserved.
// 
//---------------------------------------------------------------------------
//#define DEBUG_OUTPUT 
 
using MS.Internal;
using MS.Internal.Controls; 
using MS.Internal.Ink;
using System;
using System.Diagnostics;
using System.Collections.Generic; 
using System.Collections;
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Documents;
using System.Windows.Media; 

namespace MS.Internal.Controls
{
    ///  
    /// InkCanvasSelectionAdorner
    ///  
    internal class InkCanvasSelectionAdorner : Adorner 
    {
        ///  
        /// Constructor
        /// 
        /// The adorned InkCanvas
        internal InkCanvasSelectionAdorner(UIElement adornedElement) 
            : base(adornedElement)
        { 
            Debug.Assert(adornedElement is InkCanvasInnerCanvas, 
                "InkCanvasSelectionAdorner only should be used by InkCanvas internally");
 
            // Initialize the internal data.
            _adornerBorderPen = new Pen(Brushes.Black, 1.0);
            DoubleCollection dashes = new DoubleCollection( );
            dashes.Add(4.5); 
            dashes.Add(4.5);
            _adornerBorderPen.DashStyle = new DashStyle(dashes, 2.25); 
            _adornerBorderPen.DashCap = PenLineCap.Flat; 
            _adornerBorderPen.Freeze();
 
            _adornerPenBrush = new Pen(new SolidColorBrush(Color.FromRgb(132, 146, 222)), 1);
            _adornerPenBrush.Freeze();

            _adornerFillBrush = new LinearGradientBrush(  Color.FromRgb(240, 242, 255), //start color 
                                            Color.FromRgb(180, 207, 248),               //end color
                                            45f                                         //angle 
                                            ); 
            _adornerFillBrush.Freeze();
 
            // Create a hatch pen
            DrawingGroup hatchDG = new DrawingGroup( );
            DrawingContext dc = null;
 
            try
            { 
                dc = hatchDG.Open( ); 

                dc.DrawRectangle( 
                    Brushes.Transparent,
                    null,
                    new Rect(0.0, 0.0, 1f, 1f));
 
                Pen squareCapPen = new Pen(Brushes.Black, LineThickness);
                squareCapPen.StartLineCap = PenLineCap.Square; 
                squareCapPen.EndLineCap = PenLineCap.Square; 

                dc.DrawLine(squareCapPen, 
                    new Point(1f, 0f), new Point(0f, 1f));
            }
            finally
            { 
                if ( dc != null )
                { 
                    dc.Close( ); 
                }
            } 
            hatchDG.Freeze();

            DrawingBrush tileBrush = new DrawingBrush(hatchDG);
            tileBrush.TileMode = TileMode.Tile; 
            tileBrush.Viewport = new Rect(0, 0, HatchBorderMargin, HatchBorderMargin);
            tileBrush.ViewportUnits = BrushMappingMode.Absolute; 
            tileBrush.Freeze(); 

            _hatchPen = new Pen(tileBrush, HatchBorderMargin); 
            _hatchPen.Freeze();

            _elementsBounds = new List();
            _strokesBounds = Rect.Empty; 
        }
 
        ///  
        /// SelectionHandleHitTest
        ///  
        /// 
        /// 
        internal InkCanvasSelectionHitResult SelectionHandleHitTest(Point point)
        { 
            InkCanvasSelectionHitResult result = InkCanvasSelectionHitResult.None;
            Rect rectWireFrame = GetWireFrameRect(); 
 
            if ( !rectWireFrame.IsEmpty )
            { 
                // Hit test on the grab handles first
                for ( InkCanvasSelectionHitResult hitResult = InkCanvasSelectionHitResult.TopLeft;
                        hitResult <= InkCanvasSelectionHitResult.Left; hitResult++ )
                { 
                    Rect toleranceRect;
                    Rect visibleRect; 
                    GetHandleRect(hitResult, rectWireFrame, out visibleRect, out toleranceRect); 

                    if (toleranceRect.Contains(point)) 
                    {
                        result = hitResult;
                        break;
                    } 
                }
 
                // Now, check if we hit on the frame 
                if ( result == InkCanvasSelectionHitResult.None )
                { 
                    Rect outterRect = Rect.Inflate(rectWireFrame, CornerResizeHandleSize / 2, CornerResizeHandleSize / 2);
                    if ( outterRect.Contains(point) )
                    {
                        result = InkCanvasSelectionHitResult.Selection; 

                        // 
                    } 
                }
 
            }

            return result;
        } 

        ///  
        /// Update the selection wire frame. 
        /// Called by
        ///         InkCanvasSelection.UpdateSelectionAdorner 
        /// 
        /// 
        /// 
        internal void UpdateSelectionWireFrame(Rect strokesBounds, List hatchBounds) 
        {
            bool isStrokeBoundsDifferent = false; 
            bool isElementsBoundsDifferent = false; 

            // Check if the strokes' bounds are changed. 
            if ( _strokesBounds != strokesBounds )
            {
                _strokesBounds = strokesBounds;
                isStrokeBoundsDifferent = true; 
            }
 
            // Check if the elements' bounds are changed. 
            int count = hatchBounds.Count;
            if ( count != _elementsBounds.Count ) 
            {
                isElementsBoundsDifferent = true;
            }
            else 
            {
                for ( int i = 0; i < count; i++ ) 
                { 
                    if ( _elementsBounds[i] != hatchBounds[i] )
                    { 
                        isElementsBoundsDifferent = true;
                        break;
                    }
                } 
            }
 
 
            if ( isStrokeBoundsDifferent || isElementsBoundsDifferent )
            { 
                if ( isElementsBoundsDifferent )
                {
                    _elementsBounds = hatchBounds;
                } 

                // Invalidate our visual since the selection is changed. 
                InvalidateVisual(); 
            }
        } 

        /// 
        /// OnRender
        ///  
        /// 
        protected override void OnRender(DrawingContext drawingContext) 
        { 
            // Draw the background and hatch border around the elements
            DrawBackgound(drawingContext); 

            // Draw the selection frame.
            Rect rectWireFrame = GetWireFrameRect();
            if ( !rectWireFrame.IsEmpty ) 
            {
                // Draw the wire frame. 
                drawingContext.DrawRectangle(null, 
                    _adornerBorderPen,
                    rectWireFrame); 

                // Draw grab handles
                DrawHandles(drawingContext, rectWireFrame);
            } 
        }
 
 
        /// 
        /// Draw Handles 
        /// 
        /// 
        /// 
        private void DrawHandles(DrawingContext drawingContext, Rect rectWireFrame) 
        {
            for ( InkCanvasSelectionHitResult hitResult = InkCanvasSelectionHitResult.TopLeft; 
                    hitResult <= InkCanvasSelectionHitResult.Left; hitResult++ ) 
            {
                // Draw the handle 
                Rect toleranceRect;
                Rect visibleRect;
                GetHandleRect(hitResult, rectWireFrame, out visibleRect, out toleranceRect);
 
                drawingContext.DrawRectangle(_adornerFillBrush, _adornerPenBrush, visibleRect);
            } 
        } 

        ///  
        /// Draw the hatches and the transparent area where isn't covering the elements.
        /// 
        /// 
        private void DrawBackgound(DrawingContext drawingContext) 
        {
            PathGeometry hatchGeometry = null; 
            Geometry rectGeometry = null; 

            int count = _elementsBounds.Count; 
            if ( count != 0 )
            {
                // Create a union collection of the element regions.
                for ( int i = 0; i < count; i++ ) 
                {
                    Rect hatchRect = _elementsBounds[i]; 
 
                    if ( hatchRect.IsEmpty )
                    { 
                        continue;
                    }

                    hatchRect.Inflate(HatchBorderMargin / 2, HatchBorderMargin / 2); 

                    if ( hatchGeometry == null ) 
                    { 
                        PathFigure path = new PathFigure();
                        path.StartPoint = new Point(hatchRect.Left, hatchRect.Top); 

                        PathSegmentCollection segments = new PathSegmentCollection();

                        PathSegment line = new LineSegment(new Point(hatchRect.Right, hatchRect.Top), true); 
                        line.Freeze();
                        segments.Add(line); 
 
                        line = new LineSegment(new Point(hatchRect.Right, hatchRect.Bottom), true);
                        line.Freeze(); 
                        segments.Add(line);

                        line = new LineSegment(new Point(hatchRect.Left, hatchRect.Bottom), true);
                        line.Freeze(); 
                        segments.Add(line);
 
                        line = new LineSegment(new Point(hatchRect.Left, hatchRect.Top), true); 
                        line.Freeze();
                        segments.Add(line); 

                        segments.Freeze();
                        path.Segments = segments;
 
                        path.IsClosed = true;
                        path.Freeze(); 
 
                        hatchGeometry = new PathGeometry();
                        hatchGeometry.Figures.Add(path); 
                    }
                    else
                    {
                        rectGeometry = new RectangleGeometry(hatchRect); 
                        rectGeometry.Freeze();
 
                        hatchGeometry = Geometry.Combine(hatchGeometry, rectGeometry, GeometryCombineMode.Union, null); 
                    }
                } 
            }

            // Then, create a region which equals to "SelectionFrame - element1 bounds - element2 bounds - ..."
            GeometryGroup backgroundGeometry = new GeometryGroup( ); 
            GeometryCollection geometryCollection = new GeometryCollection();
 
            // Add the entile rectanlge to the group. 
            rectGeometry = new RectangleGeometry(new Rect(0, 0, RenderSize.Width, RenderSize.Height));
            rectGeometry.Freeze(); 
            geometryCollection.Add(rectGeometry);

            // Add the union of the element rectangles. Then the group will do oddeven operation.
            Geometry outlineGeometry = null; 

            if ( hatchGeometry != null ) 
            { 
                hatchGeometry.Freeze();
 
                outlineGeometry = hatchGeometry.GetOutlinedPathGeometry();
                outlineGeometry.Freeze();
                if ( count == 1 && ((InkCanvasInnerCanvas)AdornedElement).InkCanvas.GetSelectedStrokes().Count == 0 )
                { 
                    geometryCollection.Add(outlineGeometry);
                } 
            } 

            geometryCollection.Freeze(); 
            backgroundGeometry.Children = geometryCollection;
            backgroundGeometry.Freeze();

            // Then, draw the region which may contain holes so that the elements cannot be covered. 
            // After that, the underneath elements can receive the messages.
#if DEBUG_OUTPUT 
            // Draw the debug feedback 
            drawingContext.DrawGeometry(new SolidColorBrush(Color.FromArgb(128, 255, 255, 0)), null, backgroundGeometry);
#else 
            drawingContext.DrawGeometry(Brushes.Transparent, null, backgroundGeometry);
#endif

            // At last, draw the hatch borders 
            if ( outlineGeometry != null )
            { 
                drawingContext.DrawGeometry(null, _hatchPen, outlineGeometry); 
            }
        } 

        /// 
        /// Returns the handle rect (both visibile and the tolerance one)
        ///  
        private void GetHandleRect(InkCanvasSelectionHitResult hitResult, Rect rectWireFrame, out Rect visibleRect, out Rect toleranceRect)
        { 
            Point center = new Point(); 
            double size = 0;
            double tolerance = ResizeHandleTolerance; 

            switch ( hitResult )
            {
                case InkCanvasSelectionHitResult.TopLeft: 
                    {
                        size = CornerResizeHandleSize; 
                        center = new Point(rectWireFrame.Left, rectWireFrame.Top); 
                        break;
                    } 
                case InkCanvasSelectionHitResult.Top:
                    {
                        size = MiddleResizeHandleSize;
                        center = new Point(rectWireFrame.Left + rectWireFrame.Width / 2, rectWireFrame.Top); 
                        tolerance = (CornerResizeHandleSize - MiddleResizeHandleSize) + ResizeHandleTolerance;
                        break; 
                    } 
                case InkCanvasSelectionHitResult.TopRight:
                    { 
                        size = CornerResizeHandleSize;
                        center = new Point(rectWireFrame.Right, rectWireFrame.Top);
                        break;
                    } 
                case InkCanvasSelectionHitResult.Left:
                    { 
                        size = MiddleResizeHandleSize; 
                        center = new Point(rectWireFrame.Left, rectWireFrame.Top + rectWireFrame.Height / 2);
                        tolerance = (CornerResizeHandleSize - MiddleResizeHandleSize) + ResizeHandleTolerance; 
                        break;
                    }
                case InkCanvasSelectionHitResult.Right:
                    { 
                        size = MiddleResizeHandleSize;
                        center = new Point(rectWireFrame.Right, rectWireFrame.Top + rectWireFrame.Height / 2); 
                        tolerance = (CornerResizeHandleSize - MiddleResizeHandleSize) + ResizeHandleTolerance; 
                        break;
                    } 
                case InkCanvasSelectionHitResult.BottomLeft:
                    {
                        size = CornerResizeHandleSize;
                        center = new Point(rectWireFrame.Left, rectWireFrame.Bottom); 
                        break;
                    } 
                case InkCanvasSelectionHitResult.Bottom: 
                    {
                        size = MiddleResizeHandleSize; 
                        center = new Point(rectWireFrame.Left + rectWireFrame.Width / 2, rectWireFrame.Bottom);
                        tolerance = (CornerResizeHandleSize - MiddleResizeHandleSize) + ResizeHandleTolerance;
                        break;
                    } 
                case InkCanvasSelectionHitResult.BottomRight:
                    { 
                        size = CornerResizeHandleSize; 
                        center = new Point(rectWireFrame.Right, rectWireFrame.Bottom);
                        break; 
                    }
            }

            visibleRect = new Rect(center.X - size / 2, center.Y - size / 2, size, size); 
            toleranceRect = visibleRect;
            toleranceRect.Inflate(tolerance, tolerance); 
        } 

        ///  
        /// Returns the wire frame bounds which crosses the center of the selection handles
        /// 
        /// 
        private Rect GetWireFrameRect() 
        {
            Rect frameRect = Rect.Empty; 
            Rect selectionRect = ((InkCanvasInnerCanvas)AdornedElement).InkCanvas.GetSelectionBounds(); 

            if ( !selectionRect.IsEmpty ) 
            {
                frameRect = Rect.Inflate(selectionRect, BorderMargin, BorderMargin);
            }
 
            return frameRect;
        } 
 
        private Pen             _adornerBorderPen;
        private Pen             _adornerPenBrush; 
        private Brush           _adornerFillBrush;
        private Pen             _hatchPen;
        private Rect            _strokesBounds;
        private List      _elementsBounds; 

        // The buffer around the outside of this element 
        private const double    BorderMargin = HatchBorderMargin + 2f; 
        private const double    HatchBorderMargin = 6f;
 
        // Constants for Resize handles.
        private const int       CornerResizeHandleSize = 8;
        private const int       MiddleResizeHandleSize = 6;
        private const double    ResizeHandleTolerance = 3d; 
        private const double    LineThickness = 0.16;
 
    } 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK