Gary's page

Image:Header_documentation.gif

Getting Started

Bill likes to play with software. This drives other people nuts.

Gary is a coding wizard

Everyone knows this.

Watch what happens next

have you wondered where that "Edit" button comes from?

let's go to some code

//***************************************************************************
//
//    Copyright (c) 2006 Microsoft Corporation. All rights reserved.
//    This code is licensed under the Visual Studio SDK license terms.
//    THIS CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//***************************************************************************
using System;
using System.Collections.Generic;
using System.Text;
using System.CodeDom;

namespace Microsoft.VisualStudio.Tools.Applications.Samples.ShapeApp
{

    #region Command Base Class

    internal abstract class Command
    {
        internal abstract void Save(ICommandWriter w);
    }

    #endregion

    #region Menu Based Commands

    #region Main Menu Commands

    #region File Menu Commands

    internal class FileNewCommand : Command
    {
        /// <summary>
        /// Generates code for the FileNewCommand object.
        /// This method will generate code of the form:
        ///     this.NewDrawing();
        /// </summary>
        /// <param name="w">The command writer to write the statement to.</param>
        internal override void Save(ICommandWriter w)
        {
            CodeMethodInvokeExpression newMethodStatement =
                    new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "NewDrawing");

            w.Write(newMethodStatement);
        }
    }

    internal class FileOpenCommand : Command
    {
        private String fileName;

        internal FileOpenCommand(String fileName)
        {
            this.fileName = fileName;
        }

        /// <summary>
        /// Generates code for the FileOpenCommand object.
        /// This method will generate code of the form:
        ///     this.LoadDrawing("fileName");
        /// </summary>
        /// <param name="w">The command writer to write the statement to.</param>
        internal override void Save(ICommandWriter w)
        {
            CodeMethodInvokeExpression loadMethodStatement =
                    new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "LoadDrawing", new CodePrimitiveExpression(this.fileName));

            w.Write(loadMethodStatement);
        }
    }

    internal class FileCloseCommand : Command
    {
        /// <summary>
        /// Generates code for the FileCloseCommand object.
        /// This method will generate code of the form:
        ///     this.ActiveDrawing.Close();
        /// </summary>
        /// <param name="w">The command writer to write the statement to.</param>
        internal override void Save(ICommandWriter w)
        {
            CodePropertyReferenceExpression drawingRef =
            new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "ActiveDrawing");

            CodeMethodInvokeExpression closeMethodStatement =
                    new CodeMethodInvokeExpression(drawingRef, "Close");

            w.Write(closeMethodStatement);
        }
    }

    internal class FileCloseAllCommand : Command
    {
        /// <summary>
        /// Generates code for the FileCloseAll object.
        /// This method will generate code of the form:
        ///     for (;this.Drawings.Count > 0;)
        ///     {
        ///         this.Drawings[0].Close();
        ///     }
        /// </summary>
        /// <param name="w">The command writer to write the statement to.</param>
        internal override void Save(ICommandWriter w)
        {
            // Create references to Drawings, Drawings.Count and Drawings[0]
            CodePropertyReferenceExpression drawingsRef =
                new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Drawings");
            CodePropertyReferenceExpression countRef =
                new CodePropertyReferenceExpression(drawingsRef, "Count");
            CodeIndexerExpression drawingRef =
                new CodeIndexerExpression(drawingsRef, new CodePrimitiveExpression(0));

            // Create Initializer, Test Expression, and Increment Statement for iterator
            CodeExpressionStatement initStatement =
                new CodeExpressionStatement(new CodeSnippetExpression(String.Empty));
            CodeBinaryOperatorExpression testExpression =
                new CodeBinaryOperatorExpression(countRef, CodeBinaryOperatorType.GreaterThan, new CodePrimitiveExpression(0));
            CodeExpressionStatement incrementStatement =
                new CodeExpressionStatement(new CodeSnippetExpression(String.Empty));

            // Create the statement to execute in the for loop.
            CodeMethodInvokeExpression closeMethodStatement =
                new CodeMethodInvokeExpression(drawingRef, "Close");

            // Create the for loop.
            CodeIterationStatement iteratorStatement =
                new CodeIterationStatement(initStatement, testExpression, incrementStatement, new CodeExpressionStatement(closeMethodStatement));

            w.Write(iteratorStatement);
        }
    }

    internal class FileSaveCommand : Command
    {
        /// <summary>
        /// Generates code for the FileSaveCommand object.
        /// This method will generate code of the form:
        ///     this.ActiveDrawing.Save();
        /// </summary>
        /// <param name="w">The command writer to write the statement to.</param>
        internal override void Save(ICommandWriter w)
        {
            CodePropertyReferenceExpression drawingRef =
                new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "ActiveDrawing");

            CodeMethodInvokeExpression saveMethodStatement =
                new CodeMethodInvokeExpression(drawingRef, "Save");

            w.Write(saveMethodStatement);
        }
    }

    internal class FileSaveAllCommand : Command
    {
        /// <summary>
        /// Generates code for the FileSaveAll object.
        /// This method will generate code of the form:
        ///     int drawingIndex;
        ///     for (drawingIndex = 0; drawingIndex < this.Drawings.Count; drawingIndex = drawingIndex + 1)
        ///     {
        ///         this.Drawings[drawingIndex].Save();
        ///     }
        /// </summary>
        /// <param name="w">The command writer to write the statement to.</param>
        internal override void Save(ICommandWriter w)
        {
            // Declare and create a reference to drawingIndex
            w.Declare(typeof(int), "drawingIndex");
            CodeVariableReferenceExpression drawingIndexRef =
                new CodeVariableReferenceExpression("drawingIndex");

            // Create references to Drawings, Drawings.Count, and indexed drawings
            CodePropertyReferenceExpression drawingsRef =
                new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Drawings");
            CodePropertyReferenceExpression countRef =
                new CodePropertyReferenceExpression(drawingsRef, "Count");
            CodeIndexerExpression drawingRef =
                new CodeIndexerExpression(drawingsRef, drawingIndexRef);

            // Create Initializer, Test Expression, and Increment Statement for iterator
            CodeAssignStatement initStatement =
                new CodeAssignStatement(drawingIndexRef, new CodePrimitiveExpression(0));
            CodeBinaryOperatorExpression testExpression =
                new CodeBinaryOperatorExpression(drawingIndexRef, CodeBinaryOperatorType.LessThan, countRef);
            CodeAssignStatement incrementStatement =
                new CodeAssignStatement(drawingIndexRef,
                    new CodeBinaryOperatorExpression(drawingIndexRef, CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1)));

            // Create the statement to run in the for loop
            CodeMethodInvokeExpression saveStatement =
                new CodeMethodInvokeExpression(drawingRef, "Save");

            // Create the for loop
            CodeIterationStatement iteratorStatement =
                new CodeIterationStatement(initStatement, testExpression, incrementStatement, new CodeExpressionStatement(saveStatement));

            // Write out the code
            w.Write(iteratorStatement);
        }
    }

    internal class FileExitCommand : Command
    {
        /// <summary>
        /// Generates code for the FileExitCommand object.
        /// This method will generate code of the form:
        ///     this.Quit();
        /// </summary>
        /// <param name="w">The command writer to write the statement to.</param>
        internal override void Save(ICommandWriter w)
        {
            CodeMethodInvokeExpression quitMethodStatement =
                new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "Quit");

            w.Write(quitMethodStatement);
        }
    }

   #endregion

    #region Windows Menu Commands

    internal class WindowActivateCommand : Command
    {
        private int index;

        internal WindowActivateCommand(int index)
        {
            this.index = index;
        }

        /// <summary>
        /// Generates code for the WindowActivateCommand object.
        /// This method will generate code of the form:
        ///     this.Drawings[index].Activate();
        /// </summary>
        /// <param name="w">The command writer to write the statement to.</param>
        internal override void Save(ICommandWriter w)
        {
            CodePropertyReferenceExpression drawingsRef =
                new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Drawings");

            CodeIndexerExpression drawingRef =
                new CodeIndexerExpression(drawingsRef, new CodePrimitiveExpression(index));

            CodeMethodInvokeExpression activateMethodStatement =
                new CodeMethodInvokeExpression(drawingRef, "Activate");

            w.Write(activateMethodStatement);
        }
    }

    #endregion

    #endregion

    #region Object Based Commands

    #region Drawing Commands

    internal class DrawingShapeAddedCommand : Command
    {
        private IShape shape;

        internal DrawingShapeAddedCommand(IShape shape)
        {
            this.shape = shape;
        }

        /// <summary>
        /// Generates code for the DrawingShapeAddedCommand object.
        /// This method will generate code of the form:
        ///     IShape newShape;
        ///     newShape = this.AvailableShapes["shapeName"].Clone()
        ///     newShape.Location = this.CreatePoint(x, y);
        ///     this.ActiveDrawing.Shapes.Add(newShape);
        /// </summary>
        /// <param name="w">The command writer to write the statement to.</param>
        internal override void Save(ICommandWriter w)
        {
            w.Declare(typeof(IShape), "newShape");

            CodePropertyReferenceExpression drawingRef =
                new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "ActiveDrawing");

            CodePropertyReferenceExpression shapesRef =
                new CodePropertyReferenceExpression(drawingRef, "Shapes");

            CodePropertyReferenceExpression availRef =
                new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "AvailableShapes");

            CodeIndexerExpression shapesIndexer =
                new CodeIndexerExpression(availRef, new CodePrimitiveExpression(shape.Name));

            CodeMethodInvokeExpression cloneRef =
                new CodeMethodInvokeExpression(shapesIndexer, "Clone");

            CodeVariableReferenceExpression newShapeRef =
                new CodeVariableReferenceExpression("newShape");

            CodeAssignStatement shapeAssignStatement =
                new CodeAssignStatement(newShapeRef, cloneRef);

            w.Write(shapeAssignStatement);

            CodeMethodInvokeExpression createPointStatement =
                new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "CreatePoint", 
                new CodePrimitiveExpression(shape.Location.X), 
                new CodePrimitiveExpression(shape.Location.Y));

            CodePropertyReferenceExpression shapeLocationRef =
                new CodePropertyReferenceExpression(newShapeRef, "Location");

            CodeAssignStatement locationAssignStatement =
                new CodeAssignStatement(shapeLocationRef, createPointStatement);

            w.Write(locationAssignStatement);

            CodeMethodInvokeExpression addShape =
                    new CodeMethodInvokeExpression(shapesRef, "Add", newShapeRef);

            w.Write(addShape);
        }
    }

    internal class DrawingColorChangeCommand : Command
    {
        private Color color;

        internal DrawingColorChangeCommand(Color color)
        {
            this.color = color;
        }

        /// <summary>
        /// Generates code for the DrawingColorChangeCommand object.
        /// This method will generate code of the form:
        ///     this.ActiveDrawing.BackgroundColor = this.CreateColor(argb);
        /// </summary>
        /// <param name="w">The command writer to write the statement to.</param>
        internal override void Save(ICommandWriter w)
        {
            CodePropertyReferenceExpression drawingRef =
                new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "ActiveDrawing");

            CodePropertyReferenceExpression backgroundColorRef =
                new CodePropertyReferenceExpression(drawingRef, "BackgroundColor");

            CodeMethodInvokeExpression createColorStatement =
                new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "CreateColor",
                    new CodePrimitiveExpression(System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B).ToArgb()));

            CodeAssignStatement assignStatement =
                new CodeAssignStatement(backgroundColorRef, createColorStatement);

            w.Write(assignStatement);
        }
    }

    internal class DrawingClearCommand : Command
    {
        /// <summary>
        /// Generates code for the DrawingClearCommand object.
        /// This method will generate code of the form:
        ///     this.ActiveDrawing.Shapes.Clear();
        /// </summary>
        /// <param name="w">The command writer to write the statement to.</param>
        internal override void Save(ICommandWriter w)
        {
            CodePropertyReferenceExpression drawingRef =
                new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "ActiveDrawing");

            CodePropertyReferenceExpression shapesRef =
                new CodePropertyReferenceExpression(drawingRef, "Shapes");

            CodeMethodInvokeExpression clearMethodStatement =
                new CodeMethodInvokeExpression(shapesRef, "Clear");

            w.Write(clearMethodStatement);
        }
    }

    #endregion

    #region Shape Context Menu Commands
    internal static class CommandHelper
    {
        public static CodeExpression SelectedShapeExpression(CodeExpression preFixExpression, int shapeIndex)
        {
            CodePropertyReferenceExpression drawingRef =
                new CodePropertyReferenceExpression(preFixExpression == null ? 
                    new CodeThisReferenceExpression() : preFixExpression, "ActiveDrawing");

            CodePropertyReferenceExpression shapesRef =
                new CodePropertyReferenceExpression(drawingRef, "Shapes");

            CodeIndexerExpression shapeRef =
                new CodeIndexerExpression(shapesRef, new CodePrimitiveExpression(shapeIndex));

            return shapeRef;
        }
        public static CodeAssignStatement AssignColor(CodeExpression preFixExpression, Color color)
        {
            CodePropertyReferenceExpression colorRef =
                new CodePropertyReferenceExpression(preFixExpression == null ? 
                    new CodeThisReferenceExpression() : preFixExpression, "Color");

            CodeMethodInvokeExpression createColorStatement =
                new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "CreateColor",
                    new CodePrimitiveExpression(
                        System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B).ToArgb()));

            CodeAssignStatement assignStatement =
                new CodeAssignStatement(colorRef, createColorStatement);

            return assignStatement;
        }
    }

    internal class ShapeColorChangeCommand : Command
    {
        private int index;
        private Color color;

        internal ShapeColorChangeCommand(int index, Color color)
        {
            this.index = index;
            this.color = color;
        }

        /// <summary>
        /// Generates code for the ShapeColorChangeCommand object.
        /// This method will generate code of the form:
        ///     this.ActiveDrawing.Shapes[index].Color = this.CreateColor(argb);
        /// </summary>
        /// <param name="w">The command writer to write the statement to.</param>
        internal override void Save(ICommandWriter w)
        {
            ////refactored to one line
            //CodePropertyReferenceExpression drawingRef =
            //    new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "ActiveDrawing");

            //CodePropertyReferenceExpression shapesRef =
            //    new CodePropertyReferenceExpression(drawingRef, "Shapes");

            //CodeIndexerExpression shapeRef =
            //    new CodeIndexerExpression(shapesRef, new CodePrimitiveExpression(index));

            //CodePropertyReferenceExpression colorRef =
            //    new CodePropertyReferenceExpression(shapeRef, "Color");

            ////CodePropertyReferenceExpression colorRef =
            ////    new CodePropertyReferenceExpression(CommandHelper.SelectedShapeExpression(index), "Color");

            //CodeMethodInvokeExpression createColorStatement =
            //    new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "CreateColor",
            //        new CodePrimitiveExpression(System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B).ToArgb()));

            //CodeAssignStatement assignStatement =
            //    new CodeAssignStatement(colorRef, createColorStatement);

            //w.Write(assignStatement);
            w.Write(CommandHelper.AssignColor(
                CommandHelper.SelectedShapeExpression(null,index),color));
        }
    }

    internal class ShapeLocationChangeCommand : Command
    {
        private int index;
        private Point location;

        internal ShapeLocationChangeCommand(int index, Point location)
        {
            this.index = index;
            this.location = location;
        }

        /// <summary>
        /// Generates code for the ShapeLocationChangeCommand object.
        /// This method will generate code of the form:
        ///     this.ActiveDrawing.Shapes[index].Location = this.CreatePoint(x, y);
        /// </summary>
        /// <param name="w">The command writer to write the statement to.</param>
        internal override void Save(ICommandWriter w)
        {
            CodePropertyReferenceExpression drawingRef =
                new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "ActiveDrawing");

            CodePropertyReferenceExpression shapesRef =
                new CodePropertyReferenceExpression(drawingRef, "Shapes");

            CodeIndexerExpression shapeRef =
                new CodeIndexerExpression(shapesRef, new CodePrimitiveExpression(index));

            CodePropertyReferenceExpression locationRef =
                new CodePropertyReferenceExpression(shapeRef, "Location");

            CodeMethodInvokeExpression createPointStatement =
                new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "CreatePoint",
                    new CodePrimitiveExpression(location.X),
                    new CodePrimitiveExpression(location.Y));

            CodeAssignStatement assignStatement =
                new CodeAssignStatement(locationRef, createPointStatement);

            w.Write(assignStatement);
        }
    }

    internal class ShapeSizeChangeCommand : Command
    {
        private int index;
        private Size size;

        internal ShapeSizeChangeCommand(int index, Size size)
        {
            this.index = index;
            this.size = size;
        }

        /// <summary>
        /// Generates code for the ShapeSizeChangeCommand object.
        /// This method will generate code of the form:
        ///     this.ActiveDrawing.Shapes[index].Size = this.CreateSize(w, h);
        /// </summary>
        /// <param name="w">The command writer to write the statement to.</param>
        internal override void Save(ICommandWriter w)
        {
            CodePropertyReferenceExpression drawingRef =
                new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "ActiveDrawing");

            CodePropertyReferenceExpression shapesRef =
                new CodePropertyReferenceExpression(drawingRef, "Shapes");

            CodeIndexerExpression shapeRef =
                new CodeIndexerExpression(shapesRef, new CodePrimitiveExpression(index));

            CodePropertyReferenceExpression sizeRef =
                new CodePropertyReferenceExpression(shapeRef, "Size");

            CodeMethodInvokeExpression createSizeStatement =
                new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "CreateSize",
                    new CodePrimitiveExpression(size.Width),
                    new CodePrimitiveExpression(size.Height));

            CodeAssignStatement assignStatement =
                new CodeAssignStatement(sizeRef, createSizeStatement);

            w.Write(assignStatement);
        }
    }

    internal class ShapeDeleteCommand : Command
    {
        private int index;

        internal ShapeDeleteCommand(int index)
        {
            this.index = index;
        }

        /// <summary>
        /// Generates code for the ShapeDeleteCommand object.
        /// This method will generate code of the form:
        ///     this.ActiveDrawing.Shapes.Remove(this.ActiveDrawing.Shapes[index]);
        /// </summary>
        /// <param name="w">The command writer to write the statement to.</param>
        internal override void Save(ICommandWriter w)
        {
            CodePropertyReferenceExpression drawingRef =
                new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "ActiveDrawing");

            CodePropertyReferenceExpression shapesRef =
                new CodePropertyReferenceExpression(drawingRef, "Shapes");

            CodeIndexerExpression shapeRef =
                new CodeIndexerExpression(shapesRef, new CodePrimitiveExpression(index));

            CodeMethodInvokeExpression removeStatement =
                new CodeMethodInvokeExpression(shapesRef, "Remove", shapeRef);

            w.Write(removeStatement);
        }
    }

    #endregion

    #endregion

    #endregion

    #region Helper Methods

    #endregion

}