<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Red Stars &#187; Program</title>
	<atom:link href="http://blog.red-stars.net/category/technology/program/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.red-stars.net</link>
	<description>Programming, food, and rambling</description>
	<lastBuildDate>Sat, 08 May 2010 16:19:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>GraphicsPath Front &#8211; Vector drawing software</title>
		<link>http://blog.red-stars.net/technology/program/graphicspath-front-vector-drawing-software/</link>
		<comments>http://blog.red-stars.net/technology/program/graphicspath-front-vector-drawing-software/#comments</comments>
		<pubDate>Wed, 19 Aug 2009 02:12:49 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Program]]></category>

		<guid isPermaLink="false">http://blog.red-stars.net/?p=154</guid>
		<description><![CDATA[GraphicsPath Front is vector drawing software based upon the GraphicsPath .net class. Download (source and binaries) &#8212; Execute \bin\debug\GraphicsPathFront.exe or compile from source. Some of the notable features include: Save/load vectorized graphics, or save in numerous rasterized formats. Configurable and snap-to'able grid. Live preview of what's being drawn, including rendering in real-time. The ability to [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://red-stars.net/pictures/graphicspathfront.png" alt="screenshot" /></p>
<p>GraphicsPath Front is vector drawing software based upon the GraphicsPath .net class.</p>
<p><a href="http://red-stars.net/programs/GraphicsPathFront.zip">Download</a> (source and binaries) &mdash; Execute <code>\bin\debug\GraphicsPathFront.exe</code> or compile from source.</p>
<p>Some of the notable features include:</p>
<ul>
<li>Save/load vectorized graphics, or save in numerous rasterized formats.</li>
<li>Configurable and snap-to'able grid.</li>
<li>Live preview of what's being drawn, including rendering in real-time.</li>
<li>The ability to render as mouse input. (Need to see the videos to understand!)
<ul>
<li><a href="http://red-stars.net/pictures/renderingfont.avi">Rendering an elaborate font as mouse input to Microsoft Paint.</a></li>
<li><a href="http://red-stars.net/pictures/renderingcard.avi">Rendering a vectorized playing card as mouse input to Microsoft Paint.</a></li>
</li>
</ul>
</ul>
<p>There are several limitations in this program due to the limits of the underlying GraphicsPath class. Though the code is in place to do so, nodes can not be directly edited once created, for example. Nor can different paths be drawn using different pens.</p>
<p><span id="more-154"></span><div class='toc wptoc'>
<h2>Contents</h2>
<ol class='toc-odd level-1'>
	<li>
		<a href="#DrawingGrid_class">DrawingGrid class</a>
	</li>
	<li>
		<a href="#DrawingTools_class">DrawingTools class</a>
	</li>
</ol>
</ol>
</ol>
</div>
<div class='wptoc-end'>&nbsp;</div></p>
<p>Below are some samples of the code from the project. Note that some of the limitations of the code highlighting plugin are apparent in generics being passed as generic types, and with XML comments.</p>
<span id="DrawingGrid_class"><h3>DrawingGrid class</h3></span>
<p>The class which manages the drawing of and mouse handling for the grid.</p>
<pre class="brush:csharp">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace CrayonAutomaton {
    ///
<summary>
    /// Create a GraphicsPath based grid in memory.
    /// </summary>

    class DrawingGrid {
        ///
<summary>An event that is triggered when ever the grid is regenerated and needs to be redisplayed.</summary>

        public event Action GridUpdated;

        ///
<summary>Gets or Sets the total area of the grid.</summary>

        public Size GridSize {
            get { return _gridSize; }
            set {
                _gridSize = value;
                makeGrid();
            }
        }
        ///
<summary>Gets or Sets the size of each grid cell.</summary>

        public Size CellSize {
            get { return _cellSize; }
            set {
                _cellSize = value;
                makeGrid();
            }
        }
        ///
<summary>Gets or Sets the color of the drawn grid.</summary>

        public Color GridColor {
            get { return _gridColor; }
            set {
                _gridColor = value;
                makeGrid();
            }
        }
        ///
<summary>Gets the grid vector</summary>

        public GraphicsPath Grid { get { return path; } }
        ///
<summary>Gets or Sets if 'GridPositionFromPoint()' snaps passed Point to the grid.</summary>

        public bool SnapPointsToGrid { get; set; }
        ///
<summary>Gets or Sets if grid is drawn when asked to</summary>

        public bool Visible {
            get { return _visible; }
            set {
                _visible = value;
                if (GridUpdated != null)
                    GridUpdated();
            }
        }

        private Size _gridSize;
        private Size _cellSize;
        private Color _gridColor;
        private bool _visible;
        private bool noRendering = false;
        private GraphicsPath path = new GraphicsPath();

        public DrawingGrid(Size gridSize) : this(gridSize, new Size(20, 20), Color.LightGray, true) { }
        public DrawingGrid(Size gridSize, Size cellSize) : this(gridSize, cellSize, Color.LightGray, true) { }
        public DrawingGrid(Size gridSize, Size cellSize, Color gridColor) : this(gridSize, cellSize, gridColor, true) { }
        ///
<summary>Creates an instance of a class for drawing a grid on an image</summary>

        ///
<param name="gridSize">Total area of grid to draw</param>
        ///
<param name="cellSize">Size of each cell to draw</param>
        ///
<param name="gridColor">Color to draw the grid</param>
        ///
<param name="snapPointsToGrid">Determins if 'GridPositionFromPoint()' snaps passed Point to the grid.</param>
        public DrawingGrid(Size gridSize, Size cellSize, Color gridColor, bool snapPointsToGrid) {
            BeginUpdate();
            GridSize = gridSize;
            CellSize = cellSize;
            GridColor = gridColor;
            SnapPointsToGrid = snapPointsToGrid;
            Visible = true;
            EndUpdate();
        }

        ///
<summary>'Snaps' the passed point to grid, returns as-is if snapping to grid is disabled.</summary>

        public Point GridPositionFromPoint(Point point) {
            if (!SnapPointsToGrid)
                return point;
            Point gridPoint = new Point();
            gridPoint.X = (int)Math.Floor((decimal)(point.X / CellSize.Width)) * CellSize.Width;
            gridPoint.Y = (int)Math.Floor((decimal)(point.Y / CellSize.Height)) * CellSize.Height;
            if (point.X % CellSize.Width > CellSize.Width / 2)
                gridPoint.X += CellSize.Width;
            if (point.Y % CellSize.Height > CellSize.Height / 2)
                gridPoint.Y += CellSize.Height;
            return gridPoint;
        }
        ///
<summary>Draws grid to Graphic 'g' if Visible, regenerates grid if 'size' is different</summary>

        public void DrawToGraphic(Graphics g, Size size) {
            if (Visible) {
                if (size != GridSize)
                    GridSize = size;
                g.DrawPath(new Pen(GridColor), Grid);
            }
        }
        ///
<summary>Draws grid to Graphic 'g' if Visible</summary>

        public void DrawToGraphic(Graphics g) {
            if (Visible)
                g.DrawPath(new Pen(GridColor), Grid);
        }
        ///
<summary>Prevents (costly) regeneration of grid during property changes.</summary>

        public void BeginUpdate() { noRendering = true; }
        ///
<summary>Allows grid to be regenerated by property changes again, also regenerates grid.</summary>

        public void EndUpdate() {
            noRendering = false;
            makeGrid();
        }

        ///
<summary>(Re)render the grid to the 'path' variable.</summary>

        private void makeGrid() {
            /* Do not render if durring an 'update' */
            if (noRendering)
                return;

            int cellX = CellSize.Width;
            int cellY = CellSize.Height;

            /* Clear old grid */
            path.Reset();

            /* Add vertical lines (columes) */
            do {
                path.StartFigure();
                path.AddLine(cellX, 0, cellX, GridSize.Height);
            } while ((cellX += CellSize.Width) < GridSize.Width);

            /* Add horizontal lines (rows) */
            do {
                path.StartFigure();
                path.AddLine(0, cellY, GridSize.Width, cellY);
            } while ((cellY += CellSize.Height) < GridSize.Height);

            /* Call all grid updated events */
            if (GridUpdated != null)
                GridUpdated();
        }
    }
}</pre>
<span id="DrawingTools_class"><h3>DrawingTools class</h3></span>
<p>A collection of drawing tools and an abstract class and event driven drawing tool system.</p>
<pre class="brush:csharp">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace CrayonAutomaton {
    ///
<summary>A collection of DrawingTool</summary>

    class DrawingTools {
        ///
<summary>Event for when an update is required.</summary>

        public event Action PreviewUpdate;

        ///
<summary>Gets or Sets the currently in-use drawing tool.</summary>

        public DrawingTool Tool { get; set; }
        ///
<summary>A collection of DrawingTools</summary>

        public List<DrawingTool> Tools { get; set; }
        ///
<summary>Functions which are called on the mouse input before the mouse data is used.</summary>

        public IEnumerable<Func<Point, Point>> MouseInputFilters {
            get { return _mouseInputFilters; }
            set {
                performToAllTools(delegate(DrawingTool tool) { tool.MouseInputFilters = value; });
                _mouseInputFilters = value;
            }
        }
        public GraphicsPath Path {
            get { return _path; }
            set {
                performToAllTools(delegate(DrawingTool tool) { tool.Path = value; });
                _path = value;
            }
        }

        private GraphicsPath _path;
        private IEnumerable<Func<Point, Point>> _mouseInputFilters;

        public DrawingTools(GraphicsPath path, Func<Point, Point> mouseInputFilter/*, Control hookToSurface*/)
            : this(path, new[] { mouseInputFilter }) { }
        ///
<summary>Instances a usable collection of DrawingTool's</summary>

        ///
<param name="path">Path for the tools to draw to</param>
        public DrawingTools(GraphicsPath path, IEnumerable<Func<Point, Point>> mouseInputFilters/*, Control hookToSurface*/) {
            /* Instance all locally coded drawing tools */
            Tools = new List<DrawingTool>(new DrawingTool[] {
                new NullDrawingTool(),
                new LineDrawingTool(),
                new RectangleDrawingTool(),
                new EllipseDrawingTool(),
                new FreeDrawDrawingTool(),
                new TextDrawingTool()
            });

            /* Set-up all required members */
            performToAllTools(delegate(DrawingTool tool) { tool.ParentCollection = this; });
            Path = path;
            MouseInputFilters = mouseInputFilters;

            SetTool("");
        }

        public void Preview() {
            if (PreviewUpdate != null)
                PreviewUpdate();
        }
        public void HookToolsToSurface(Control surface) {

        }

        public bool SetTool(DrawingTool tool) { return SetTool(tool.Name); }
        ///
<summary>Changes the in-use tool based upon 'name'</summary>

        /// <returns>Returns 'true' if a tool is found and set, 'false' otherwise.</returns>
        public bool SetTool(string name) {
            foreach (DrawingTool curTool in Tools)
                if (curTool.Name == name) {
                    Tool = curTool;
                    return true;
                }
            return false;
        }

        private void performToAllTools(Action<DrawingTool> delegateFunction) {
            foreach (DrawingTool curTool in Tools)
                delegateFunction(curTool);
        }
    }

    abstract class DrawingTool : IEquatable<DrawingTool> {
        ///
<summary>Get the tools name</summary>

        public string Name { get { return _name; } }
        ///
<summary>A value indicating if the mouse is presently inside the drawing area</summary>

        public bool IsMouseInside { get; set; }
        public GraphicsPath Path { get; set; }
        public IEnumerable<Func<Point, Point>> MouseInputFilters { get; set; }
        public MouseButtons MouseButtonState { get; set; }
        public DrawingTools ParentCollection { get; set; }

        private string _name;

        protected Point mouseDownLocation;

        ///
<summary>Abstract class for drawing tools</summary>

        ///
<param name="name">Name of the drawing tool, must be unique</param>
        protected DrawingTool(string name) {
            _name = name;
            IsMouseInside = false;
        }

        ///
<summary>Call to pass the mouse down event to the in-use tool.</summary>

        public void MouseDown(Point point) {
            point = filterMouseInput(point);
            mouseDownLocation = point;
            mouseDown(point);
        }
        ///
<summary>Call to pass the mouse move event to the in-use tool.</summary>

        public void MouseMove(Point point) {
            point = filterMouseInput(point);
            mouseMove(point);
        }
        ///
<summary>Call to pass the mouse up event to the in-use tool.</summary>

        public void MouseUp(Point point) {
            point = filterMouseInput(point);
            mouseUp(point);
        }
        public void MouseLeave() {
            IsMouseInside = false;
            mouseLeave();
        }
        public void MouseEnter() {
            IsMouseInside = true;
            mouseEnter();
        }
        public void Render(Point currentMouseLocation) { Render(Path, currentMouseLocation); }
        public void Render(GraphicsPath path, Point currentMouseLocation) {
            render(path, filterMouseInput(currentMouseLocation));
        }

        protected virtual void mouseMove(Point point) {}
        protected virtual void mouseUp(Point point) { }

        ///
<summary>This function should be override if it's possible to render with mouseDownLocation and the currentMouseLocation.
        /// If this function is not overloaded, drawing is still possible, but preview rendering is not.</summary>

        protected virtual void render(GraphicsPath path, Point currentMouseLocation) { }
        ///
<summary>Override if mouse down detection is needed</summary>

        protected virtual void mouseDown(Point point) { }
        ///
<summary>Override if mouse enter detection is needed</summary>

        protected virtual void mouseEnter() { }
        ///
<summary>Override if mouse up detection is needed</summary>

        protected virtual void mouseLeave() { }

        ///
<summary>Returns passed point as processed by the list of provided filters in MouseFilterList</summary>

        protected Point filterMouseInput(Point point) {
            foreach (Func<Point, Point> curFilter in MouseInputFilters)
                point = curFilter(point);
            return point;
        }
        ///
<summary>Reorders the passed points so that point1 is to the upper left of point2</summary>

        /// <returns>Returns the distance between refactored point1 and point2</returns>
        protected Size orderPoints(ref Point point1, ref Point point2) {
            point1.X = Math.Min(point1.X, point2.X);
            point1.Y = Math.Min(point1.Y, point2.Y);
            point2.X = Math.Max(point1.X, point2.X);
            point2.Y = Math.Max(point1.Y, point2.Y);
            return new Size(point2.X - point1.X, point2.Y - point1.Y);
        }
        ///
<summary>Returns a rectangle from where MouseDown and mouseUpPoint occured</summary>

        protected Rectangle mouseDragRectangle(Point mouseUpPoint) {
            return new Rectangle(mouseDownLocation, orderPoints(ref mouseDownLocation, ref mouseUpPoint));
        }

        public override string ToString() { return Name; }
        public bool Equals(DrawingTool obj) { return obj.GetHashCode() == GetHashCode(); }
        public override int GetHashCode() { return Name.GetHashCode(); }
    }

    ///
<summary>A base level null drawing tool for default tool selection</summary>

    class NullDrawingTool : DrawingTool {
        public NullDrawingTool()
            : base(string.Empty) { }
    }

    ///
<summary>A DrawingTool for drawing single lines</summary>

    class LineDrawingTool : DrawingTool {
        public LineDrawingTool()
            : base("Line") { }

        protected override void render(GraphicsPath path, Point currentMouseLocation) {
            path.AddLine(mouseDownLocation, currentMouseLocation);
        }

        protected override void mouseUp(Point point) {
            Render(point);
        }
    }

    ///
<summary>A DrawingTool for drawing single rectangles</summary>

    class RectangleDrawingTool : DrawingTool {
        public RectangleDrawingTool()
            : base("Rectangle") { }

        protected override void render(GraphicsPath path, Point currentMouseLocation) {
            path.AddRectangle(mouseDragRectangle(currentMouseLocation));
        }

        protected override void mouseUp(Point point) {
            Render(point);
        }
    }

    ///
<summary>A DrawingTool for drawing single ellipses</summary>

    class EllipseDrawingTool : DrawingTool {
        public EllipseDrawingTool()
            : base("Ellipse") { }

        protected override void render(GraphicsPath path, Point currentMouseLocation) {
            path.AddEllipse(mouseDragRectangle(currentMouseLocation));
        }

        protected override void mouseUp(Point point) {
            Render(point);
        }
    }

    ///
<summary>A DrawingTool for 'free hand' drawing</summary>

    class FreeDrawDrawingTool : DrawingTool {
        Point lastPoint;

        public FreeDrawDrawingTool()
            : base("Free Draw") { }
        protected override void mouseDown(Point point) {
            lastPoint = point;
        }
        protected override void mouseMove(Point point) {
            if (MouseButtonState == MouseButtons.Left) {
                drawLine(point);
                lastPoint = point;
            }
        }
        protected override void mouseUp(Point point) {
            drawLine(point);
        }

        private void drawLine(Point point) {
            Path.AddLine(lastPoint, point);
        }
    }

    class TextDrawingTool : DrawingTool {
        public TextDrawingTool()
            : base("Text") { }

        enterTextDialog textDialog;

        protected override void mouseUp(Point point) {
            textDialog = new enterTextDialog(ParentCollection.Preview);
            if (textDialog.ShowDialog() == DialogResult.OK)
                render(Path, point);
        }

        void textDialog_PreviewUpdateEvent() {
        }

        protected override void render(GraphicsPath path, Point currentMouseLocation) {
            path.AddString(textDialog.EnteredText,
                textDialog.SelectedFont.FontFamily,
                (int)textDialog.SelectedFont.Style,
                textDialog.SelectedFont.Size,
                mouseDownLocation,
                StringFormat.GenericDefault);
        }
    }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.red-stars.net/technology/program/graphicspath-front-vector-drawing-software/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://red-stars.net/pictures/renderingfont.avi" length="1108164" type="video/x-msvideo" />
<enclosure url="http://red-stars.net/pictures/renderingcard.avi" length="216944" type="video/x-msvideo" />
		</item>
		<item>
		<title>Boggle.exe</title>
		<link>http://blog.red-stars.net/technology/program/boggle-exe/</link>
		<comments>http://blog.red-stars.net/technology/program/boggle-exe/#comments</comments>
		<pubDate>Wed, 19 Aug 2009 01:54:28 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Program]]></category>

		<guid isPermaLink="false">http://blog.red-stars.net/?p=150</guid>
		<description><![CDATA[Boggle.exe is a computerized version of the Hasbro dice game. It's intended to be played by multiple people infront of the computer using pens and paper, no internet play is supported as it's ridiculously easy to cheat. The main neat feature of Boggle.exe over it's physical counterpart is a board solver. Once the game is [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://red-stars.net/pictures/boggle.png" alt="screenshot" /></p>
<p><em>Boggle.exe</em> is a computerized version of the Hasbro dice game. It's intended to be played by multiple people infront of the computer using pens and paper, no internet play is supported as it's ridiculously easy to cheat. The main neat feature of Boggle.exe over it's physical counterpart is a board solver. Once the game is over, all of the valid words inside of the board are shown and can be highlighted (see picture).</p>
<p><a href="http://red-stars.net/programs/Boggle.zip">Download</a> (source and executable) &mdash; Extract to it's own directory and run <code>\bin\debug\Boggle.exe</code>. words.txt must be in the same directory as the executable.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.red-stars.net/technology/program/boggle-exe/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
