asciipumper

- mspaint style program to create irc ascii art
git clone git://git.acid.vegas/asciipumper.git
Log | Files | Refs | Archive | README

PaintCanvas.cs (35392B)

      1 #region Copyright (c) 2007, PP4L Software
      2 /************************************************************************************
      3 
      4 Copyright  2007, PP4L Software
      5 Author:	Lampiasis <lampiasis@dvolker.com>
      6 
      7 This program is free software; you can redistribute it and/or modify
      8 it under the terms of the GNU General Public License as published by
      9 the Free Software Foundation; either version 2 of the License, or
     10 (at your option) any later version.
     11 
     12 This program is distributed in the hope that it will be useful,
     13 but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with this program; if not, write to the Free Software
     19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
     20 
     21 '***********************************************************************************/
     22 #endregion
     23 
     24 using System;
     25 using System.Collections.Generic;
     26 using System.ComponentModel;
     27 using System.Drawing;
     28 using System.Data;
     29 using System.Text;
     30 using System.Windows.Forms;
     31 using System.IO;
     32 using System.Text.RegularExpressions;
     33 using System.Drawing.Printing;
     34 
     35 
     36 namespace AsciiPumper
     37 {
     38 	public partial class PaintCanvas : UserControl
     39 	{
     40 		public PaintCanvas()
     41 		{
     42 			InitializeComponent();
     43 
     44 			CellRows = new List<List<CellInfo>>();
     45 			ResizeCellRows();
     46 
     47 
     48 			UpdateSeperatorPen();
     49 			PaintCanvas_SizeChanged(this, EventArgs.Empty);
     50 			PaintIntoBackground();
     51 			Program.Settings.PropertyChanged += new PropertyChangedEventHandler(Settings_PropertyChanged);
     52 
     53 		}
     54 
     55 
     56 		public Stack<IUndoableAction> UndoList = new Stack<IUndoableAction>();
     57 		public Stack<IUndoableAction> RedoList = new Stack<IUndoableAction>();
     58 		public IUndoableAction CurrentAction;
     59 
     60 		private bool m_Modified;
     61 
     62 		/// <summary>
     63 		/// Gets or sets the Modified.
     64 		/// </summary>
     65 		public bool Modified
     66 		{
     67 			get { return m_Modified; }
     68 			set
     69 			{
     70 				if (m_Modified != value)
     71 				{
     72 					if (value == true)
     73 						OnCanvasModified(CanvasModifiedEventArgs.Empty);
     74 					m_Modified = value;
     75 				}
     76 			}
     77 		}
     78 
     79 		public class CanvasModifiedEventArgs : EventArgs
     80 		{
     81 			public static readonly new CanvasModifiedEventArgs Empty = new CanvasModifiedEventArgs();
     82 		}
     83 
     84 		public event EventHandler<CanvasModifiedEventArgs> CanvasModified;
     85 
     86 		protected virtual void OnCanvasModified(CanvasModifiedEventArgs e)
     87 		{
     88 			EventHandler<CanvasModifiedEventArgs> handler = CanvasModified;
     89 			if (handler != null)
     90 			{
     91 				handler(this, e);
     92 			}
     93 		}
     94 
     95 		public void CompleteRepaint()
     96 		{
     97 			this.PaintIntoBackground();
     98 			this.Invalidate();
     99 		}
    100 
    101 		void Settings_PropertyChanged(object sender, PropertyChangedEventArgs e)
    102 		{
    103 			bool invalidate = false;
    104 
    105 			if ( e.PropertyName == "PaintFontName" )
    106 			{
    107 				this.Font = new Font((string) Program.Settings["PaintFontName"], (float) Program.Settings["PaintFontSize"]);
    108 				invalidate = true;
    109 			}
    110 			if (e.PropertyName == "PaintFontSize")
    111 			{
    112 				this.Font = new Font((string) Program.Settings["PaintFontName"], (float) Program.Settings["PaintFontSize"]);
    113 				invalidate = true;
    114 			}
    115 			if (e.PropertyName == "CellWidth")
    116 			{
    117 				this.CellWidth = Program.Settings.CellWidth;
    118 				invalidate = true;
    119 			}
    120 			if (e.PropertyName == "CellHeight")
    121 			{
    122 				this.CellHeight = Program.Settings.CellHeight;
    123 				invalidate = true;
    124 			}
    125 			if (e.PropertyName == "SeperatorColor")
    126 				this.SeperatorColor = Program.Settings.SeperatorColor;
    127 			if (e.PropertyName == "HighlightColor")
    128 				this.HighlightColor = Program.Settings.HighlightColor;
    129 
    130 			if (invalidate)
    131 			{
    132 			//	this.PaintIntoBackground();
    133 			//	this.Invalidate();
    134 			}
    135 		}
    136 
    137 		private void ResizeCellRows( )
    138 		{
    139 			for (int rows = 0; rows < this.Rows; rows++)
    140 			{
    141 				if ( CellRows.Count < rows + 1 ) 
    142 					CellRows.Add(new List<CellInfo>(this.Columns));
    143 				for (int cols = 0; cols < this.Columns; cols++)
    144 				{
    145 					if ( CellRows[rows].Count < cols + 1 )
    146 						CellRows[rows].Add( new CellInfo() );
    147 				}
    148 			}
    149 		}
    150     
    151 
    152 		private void PaintCanvas_Paint(object sender, PaintEventArgs e)
    153 		{
    154 #if false
    155 			// test
    156 			Font consolas = new Font("Consolas", 18);
    157 			m_PaintBuffer.DrawString("Test", consolas, Brushes.BlueViolet, 10, consolas.Height);
    158 			SizeF size = m_PaintBuffer.MeasureString("Test", consolas);
    159 			m_PaintBuffer.DrawString(size.Width.ToString(), consolas, Brushes.Blue, size.Width + 10, consolas.Height);
    160 			// test
    161 			Font arial = new Font("Arial", 10);
    162 			m_PaintBuffer.DrawString("Test", arial, Brushes.BlueViolet, 10, 40);
    163 			size = m_PaintBuffer.MeasureString("Test", arial);
    164 			m_PaintBuffer.DrawString(size.Width.ToString(), arial, Brushes.Blue, size.Width + 10, 40);
    165 #endif
    166 		}
    167 
    168 		private Image m_PaintImage;
    169 
    170 		private Graphics m_PaintBuffer;
    171 
    172 
    173 		protected override void OnPaint(PaintEventArgs e)
    174 		{
    175 			base.OnPaint(e);
    176 			// PaintIntoBackground();
    177 			e.Graphics.DrawImage(m_PaintImage, e.ClipRectangle, e.ClipRectangle, GraphicsUnit.Pixel); // DrawImageUnscaledAndClipped(m_PaintImage., e.ClipRectangle);
    178 
    179 
    180 		}
    181 
    182 		public void PrintToGraphicDevice(Graphics graphics, PrintPageEventArgs e )
    183 		{
    184 			Rectangle printRect = new Rectangle(
    185 				e.MarginBounds.Top, e.MarginBounds.Left ,
    186 				Math.Min(m_PaintImage.Width, e.MarginBounds.Right - e.MarginBounds.Left),
    187 				Math.Min(m_PaintImage.Height, e.MarginBounds.Bottom - e.MarginBounds.Top)
    188 				);
    189 			
    190 			graphics.DrawImage(m_PaintImage, printRect, new Rectangle(0, 0, m_PaintImage.Width, m_PaintImage.Height), GraphicsUnit.Pixel);
    191 		}
    192 
    193 		private void ResizeByCellSize()
    194 		{
    195 			this.Height = /*(m_Rows * ( m_SeperatorWidth / 2)) +*/ (m_Rows * m_CellHeight);
    196 			this.Width = (m_Columns * (m_SeperatorWidth / 2)) + (m_Columns * m_CellWidth);
    197 
    198 		} 
    199 
    200 		private Point m_SelectedCellPosition = new Point(0,0);
    201 
    202 		/// <summary>
    203 		/// Gets or sets the SelectedCellPosition.
    204 		/// </summary>
    205 		public Point SelectedCellPosition
    206 		{
    207 			get { return m_SelectedCellPosition; }
    208 			set { RepaintSingleCell(m_SelectedCellPosition); m_SelectedCellPosition = value; RepaintSingleCell(m_SelectedCellPosition); }
    209 		}
    210 
    211 		#region Highlight Properties and methods
    212 		private void UpdateHighlightPen()
    213 		{
    214 			m_HighlightPen = new Pen(m_HighlightColor, m_HighlightWidth);
    215 			
    216 		}
    217 
    218 		private Pen m_HighlightPen = Pens.OldLace;
    219 
    220 		private Color m_HighlightColor = Color.OldLace;
    221 
    222 		/// <summary>
    223 		/// Gets or sets the HighlightColor.
    224 		/// </summary>
    225 		public Color HighlightColor
    226 		{
    227 			get { return m_HighlightColor; }
    228 			set { m_HighlightColor = value; UpdateHighlightPen(); PaintIntoBackground();  this.Invalidate(); }
    229 		}
    230 
    231 		private int m_HighlightWidth = 2;
    232 
    233 		/// <summary>
    234 		/// Gets or sets the HighlightWidth.
    235 		/// </summary>
    236 		public int HighlightWidth
    237 		{
    238 			get { return m_HighlightWidth; }
    239 			set { m_HighlightWidth = value; UpdateHighlightPen(); PaintIntoBackground(); this.Invalidate(); }
    240 		}
    241 		#endregion
    242 
    243 		private int m_SeperatorWidth = 1;
    244 
    245 		/// <summary>
    246 		/// Gets or sets the SeperatorWidth.
    247 		/// </summary>
    248 		public int SeperatorWidth
    249 		{
    250 			get { return m_SeperatorWidth; }
    251 			set { m_SeperatorWidth = value; UpdateSeperatorPen(); ResizeByCellSize(); PaintIntoBackground();  this.Invalidate(); }
    252 		}
    253 
    254 		private int m_CellWidth = 5;
    255 
    256 		/// <summary>
    257 		/// Gets or sets the CellWidth.
    258 		/// </summary>
    259 		public int CellWidth
    260 		{
    261 			get { return m_CellWidth; }
    262 			set { m_CellWidth = value; ResizeByCellSize(); PaintIntoBackground(); this.Invalidate(); }
    263 		}
    264 
    265 		private int m_CellHeight = 10;
    266 
    267 		/// <summary>
    268 		/// Gets or sets the CellHeight.
    269 		/// </summary>
    270 		public int CellHeight
    271 		{
    272 			get { return m_CellHeight; }
    273 			set { m_CellHeight = value; ResizeByCellSize(); PaintIntoBackground(); this.Invalidate(); }
    274 		}
    275 
    276 		private int m_Columns = 60;
    277 
    278 		/// <summary>
    279 		/// Gets or sets the Columns.
    280 		/// </summary>
    281 		public int Columns 
    282 		{
    283 			get { return m_Columns; }
    284 			set { m_Columns = value; ResizeCellRows(); ResizeByCellSize(); PaintIntoBackground(); this.Invalidate(); }
    285 		}
    286 
    287 		private int m_Rows = 20;
    288 
    289 		/// <summary>
    290 		/// Gets or sets the Rows.
    291 		/// </summary>
    292 		public int Rows
    293 		{
    294 			get { return m_Rows; }
    295 			set { m_Rows = value; ResizeCellRows(); ResizeByCellSize(); PaintIntoBackground();  this.Invalidate(); }
    296 		}
    297 
    298 
    299 		private Color m_SeperatorColor = Color.DarkGray;
    300 
    301 		/// <summary>
    302 		/// Gets or sets the SeperatorColor.
    303 		/// </summary>
    304 		public Color SeperatorColor
    305 		{
    306 			get { return m_SeperatorColor; }
    307 			set { m_SeperatorColor = value; UpdateSeperatorPen(); this.Invalidate(); }
    308 		}
    309 
    310 		private Pen m_SeperatorPen;
    311 
    312 		private void UpdateSeperatorPen()
    313 		{
    314 			m_SeperatorPen = new Pen(m_SeperatorColor, m_SeperatorWidth);
    315 		}
    316 
    317 		private void RepaintSingleCell(Point cellpos)
    318 		{
    319 			if ( m_DontRepaint )
    320 				return;
    321 
    322 			if (cellpos.X < 0 || cellpos.Y < 0 || cellpos.Y >= CellRows.Count || cellpos.X >= CellRows[0].Count)
    323 				return;
    324 
    325 			
    326 			
    327 			/* int max_x = cellpos.X + 1;
    328 			int max_y = cellpos.Y + 1;
    329 			for (cellpos.X--; cellpos.X < max_x; cellpos.X++)
    330 			{
    331 				for (cellpos.Y--; cellpos.Y < max_y; cellpos.Y++)
    332 				{
    333 					if (cellpos.Y < 0 || cellpos.X < 0)
    334 						continue;
    335 			 */
    336 		
    337 					CellInfo ci = CellRows[cellpos.Y][cellpos.X];
    338 					//m_PaintBuffer.FillRectangle(new SolidBrush(this.BackColor), cellpos.X * m_CellWidth, cellpos.Y * m_CellHeight, m_CellWidth, m_CellHeight);
    339 					m_PaintBuffer.FillRectangle(this.Colors.SolidBrushes[ci.BackColor], cellpos.X * m_CellWidth, cellpos.Y * m_CellHeight, m_CellWidth, m_CellHeight);
    340 					if (CellRows[cellpos.Y][cellpos.X].Character != ' ')
    341 					{
    342 						FontStyle styles = new FontStyle();
    343 						if (ci.Bold)
    344 							styles |= FontStyle.Bold;
    345 						if (ci.Underlined)
    346 							styles |= FontStyle.Underline;
    347 						Font font = new Font(this.Font, styles);
    348 						m_PaintBuffer.DrawString(ci.Character.ToString(), font,this.Colors.SolidBrushes[ci.ForeColor], cellpos.X * m_CellWidth, cellpos.Y * m_CellHeight);
    349 
    350 					}
    351 					m_PaintBuffer.DrawLine(m_SeperatorPen, cellpos.X * m_CellWidth, (1 + cellpos.Y) * m_CellHeight, (1 + cellpos.X) * m_CellWidth, (1 + cellpos.Y) * m_CellHeight);
    352 					m_PaintBuffer.DrawLine(m_SeperatorPen, (1 + cellpos.X) * m_CellWidth, (cellpos.Y) * m_CellHeight, (1 + cellpos.X) * m_CellWidth, (1 + cellpos.Y) * m_CellHeight);
    353 					m_PaintBuffer.DrawLine(m_SeperatorPen, (cellpos.X) * m_CellWidth, (cellpos.Y) * m_CellHeight, (1 + cellpos.X) * m_CellWidth, (cellpos.Y) * m_CellHeight);
    354 					m_PaintBuffer.DrawLine(m_SeperatorPen, (cellpos.X) * m_CellWidth, (cellpos.Y) * m_CellHeight, (cellpos.X) * m_CellWidth, (1 + cellpos.Y) * m_CellHeight);
    355 					if (m_SelectedCellPosition.X == cellpos.X && m_SelectedCellPosition.Y == cellpos.Y)
    356 					{
    357 						m_PaintBuffer.DrawRectangle(m_HighlightPen, 1 + (m_SelectedCellPosition.X * (m_CellWidth + (m_SeperatorWidth / 2))), 1 + ( m_SelectedCellPosition.Y * (m_CellHeight + (m_SeperatorWidth / 2)) ),
    358 										 m_CellWidth - 2, m_CellHeight - 2);
    359 					}
    360 			//	}
    361 			//}
    362 			int xpos = (cellpos.X * m_CellWidth) - 5;
    363 			int ypos = (cellpos.Y * m_CellHeight) - 5;
    364 			if ( xpos < 0 ) 
    365 				xpos = 0;
    366 			if ( ypos < 0 )
    367 				ypos = 0;
    368 			this.Invalidate(new Rectangle(new Point(xpos, ypos), new Size(m_CellWidth + 5, m_CellHeight + 5)));
    369 		}
    370 
    371 		private void PaintIntoBackground()
    372 		{
    373 			if ( m_DontRepaint )
    374 				return;
    375 			//m_PaintBuffer.FillRectangle(new SolidBrush(this.BackColor), 0, 0, this.Width, this.Height);
    376 
    377 			Font boldfont = new Font(this.Font, FontStyle.Bold);
    378 			Font underlinedfont = new Font(this.Font, FontStyle.Underline);
    379 			Font bold_underlined_font = new Font(this.Font, FontStyle.Underline | FontStyle.Bold);
    380 
    381 			CellInfo ci;
    382 			for (int row = 0; row < m_Rows; row++)
    383 			{
    384 				for (int col = 0; col < m_Columns; col++)
    385 				{
    386 					ci = CellRows[row][col];
    387 					m_PaintBuffer.FillRectangle(this.Colors.SolidBrushes[ci.BackColor], col * m_CellWidth, row * m_CellHeight, m_CellWidth, m_CellHeight);
    388 					if (CellRows[row][col].Character != ' ')
    389 					{
    390 						Font font;
    391 						if (ci.Bold && ci.Underlined)
    392 							font = bold_underlined_font;
    393 						else if (ci.Bold)
    394 							font = boldfont;
    395 						else if (ci.Underlined)
    396 							font = underlinedfont;
    397 						else
    398 							font = this.Font;
    399 						m_PaintBuffer.DrawString(ci.Character.ToString(), font, this.Colors.SolidBrushes[ci.ForeColor], col * m_CellWidth, row * m_CellHeight);
    400 
    401 					}
    402 				}
    403 			}
    404 			for (int i = 0; i < m_Rows; i++)
    405 			{
    406 				int ypos = (m_SeperatorWidth / 2) + i * m_CellHeight;
    407 				m_PaintBuffer.DrawLine(m_SeperatorPen, 0, ypos, this.Width, ypos);
    408 
    409 			}
    410 			for (int i = 0; i < m_Columns; i++)
    411 			{
    412 				int xpos = (m_SeperatorWidth / 2) + i * m_CellWidth;
    413 				m_PaintBuffer.DrawLine(m_SeperatorPen, xpos, 0, xpos, this.Height);
    414 
    415 			}
    416 
    417 			m_PaintBuffer.DrawRectangle(m_HighlightPen, m_SelectedCellPosition.X * (m_CellWidth + (m_SeperatorWidth / 2)), m_SelectedCellPosition.Y * (m_CellHeight + (m_SeperatorWidth / 2)),
    418 				 m_CellWidth, m_CellHeight);
    419 
    420 			
    421 #if false
    422 			// test
    423 			Font consolas = new Font("Consolas", 18, GraphicsUnit.Pixel);
    424 			m_PaintBuffer.DrawString("Test", consolas, Brushes.BlueViolet, 10, 0);
    425 			SizeF size = m_PaintBuffer.MeasureString("Test", consolas);
    426 			m_PaintBuffer.DrawString(size.Width.ToString(), consolas, Brushes.Blue, size.Width + 10, 0);
    427 			m_PaintBuffer.DrawLine(new Pen(Brushes.AliceBlue), new Point(0, consolas.Height), new Point(this.Width, consolas.Height));
    428 			// test
    429 			Font arial = new Font("Arial", 10, GraphicsUnit.Pixel);
    430 			
    431 			m_PaintBuffer.DrawString("Test", arial, Brushes.BlueViolet, 10, consolas.Height);
    432 			size = m_PaintBuffer.MeasureString("Test", arial);
    433 			m_PaintBuffer.DrawString(size.Width.ToString(), arial, Brushes.Blue, size.Width + 10, consolas.Height);
    434 			m_PaintBuffer.DrawLine(new Pen(Brushes.Peru), new Point(0, consolas.Height + arial.Height), new Point(this.Width, consolas.Height + arial.Height));
    435 #endif
    436 		}
    437 
    438 		private void PaintCanvas_SizeChanged(object sender, EventArgs e)
    439 		{
    440 			m_PaintImage = new Bitmap(this.Width, this.Height, System.Drawing.Imaging.PixelFormat.Format16bppRgb565); //.Format32bppRgb);
    441 			m_PaintBuffer = Graphics.FromImage(m_PaintImage);
    442 			PaintIntoBackground();
    443 		}
    444 
    445 		public enum PaintModes
    446 		{
    447 			PaintBrush,
    448 			Fill,
    449 			Bold,
    450 			Underline,
    451 			RemoveFormatting
    452 		};
    453 
    454 		private PaintModes m_PaintMode;
    455 
    456 		/// <summary>
    457 		/// Gets or sets the PaintMode.
    458 		/// </summary>
    459 		public PaintModes PaintMode
    460 		{
    461 			get { return m_PaintMode; }
    462 			set { m_PaintMode = value; }
    463 		}
    464 
    465 		private void PaintCanvas_MouseDown(object sender, MouseEventArgs e)
    466 		{
    467 			if (CurrentAction is KeypressAction)
    468 			{
    469 				CurrentAction = null;
    470 			}
    471 
    472 			if (CurrentAction == null)
    473 			{
    474 				if ( m_PaintMode == PaintModes.PaintBrush || m_PaintMode == PaintModes.Fill )
    475 					CurrentAction = new PaintAction();
    476 			}
    477 			SelectAppropriateCell(e.X, e.Y);
    478 			if (m_PaintMode == PaintModes.PaintBrush || m_PaintMode == PaintModes.Fill)
    479 				PaintCellByMouseArgs(this.m_SelectedCellPosition, e);
    480 			else if (m_PaintMode == PaintModes.Bold)
    481 			{
    482 				BoldSelectedCell();
    483 			}
    484 			else if (m_PaintMode == PaintModes.Underline)
    485 			{
    486 				UnderlineSelectedCell();
    487 			}
    488 			else if (m_PaintMode == PaintModes.RemoveFormatting)
    489 			{
    490 				RemoveFormattingSelectedCell();
    491 			}
    492 		}
    493 
    494 		private void RemoveFormattingSelectedCell()
    495 		{
    496 			SelectedCell.Underlined = false;
    497 			SelectedCell.Bold = false;
    498 			RepaintSingleCell(SelectedCellPosition);
    499 		}
    500 
    501 		public void UnderlineSelectedCell()
    502 		{
    503 			SelectedCell.Underlined = true;
    504 			RepaintSingleCell(SelectedCellPosition);
    505 		}
    506 
    507 		public void BoldSelectedCell()
    508 		{
    509 			SelectedCell.Bold = true; //  (SelectedCell.Bold ? false : true); 
    510 			RepaintSingleCell(SelectedCellPosition);
    511 		}
    512 
    513 		private void StartFillCell( Point point, byte origcolor, byte color, bool foreground)
    514 		{
    515 			if (CurrentAction is PaintAction)
    516 			{
    517 				//CurrentAction = new PaintAction();
    518 				((PaintAction)CurrentAction).IsForeground = foreground;
    519 				((PaintAction)CurrentAction).NewPaintColor = color;
    520 				((PaintAction)CurrentAction).OldPaintColor = origcolor;
    521 			}
    522 			FillCell(  point,  origcolor,  color,  foreground);
    523 			if (CurrentAction is PaintAction)
    524 			{
    525 				AddUndoAction(CurrentAction);
    526 				CurrentAction = null;
    527 			}
    528 		}
    529 
    530 		private void PaintCellByMouseArgs(Point point, MouseEventArgs e)
    531 		{
    532 
    533 
    534 			switch (e.Button)
    535 			{
    536 				case MouseButtons.Left:
    537 					if ( m_PaintMode == PaintModes.Fill )
    538 					{
    539 						if ( m_LeftMouseIsForeground )
    540 							StartFillCell(point, CellRows[point.Y][point.X].ForeColor, m_LeftMouseColor, m_LeftMouseIsForeground);
    541 						else
    542 							StartFillCell(point, CellRows[point.Y][point.X].BackColor, m_LeftMouseColor, m_LeftMouseIsForeground);
    543 						this.Invalidate();
    544 					}
    545 					else
    546 						PaintCell(point, m_LeftMouseColor, m_LeftMouseIsForeground);
    547 					if (m_LeftMouseIsForeground)
    548 						this.MostRecentForegroundColor = m_LeftMouseColor;
    549 					break;
    550 				case MouseButtons.Right:
    551 					if (m_PaintMode == PaintModes.Fill)
    552 					{
    553 						if (m_RightMouseIsForeground)
    554 							StartFillCell(point, CellRows[point.Y][point.X].ForeColor, m_RightMouseColor, m_RightMouseIsForeground);
    555 						else
    556 							StartFillCell(point, CellRows[point.Y][point.X].BackColor, m_RightMouseColor, m_RightMouseIsForeground);
    557 						this.Invalidate();
    558 					}
    559 					else
    560 						PaintCell(point, m_RightMouseColor, m_RightMouseIsForeground);
    561 					if (m_RightMouseIsForeground)
    562 						this.MostRecentForegroundColor = m_RightMouseColor;
    563 					break;
    564 				case MouseButtons.Middle:
    565 					if (m_PaintMode == PaintModes.Fill)
    566 					{
    567 						if (m_MiddleMouseIsForeground)
    568 							StartFillCell(point, CellRows[point.Y][point.X].ForeColor, m_MiddleMouseColor, m_MiddleMouseIsForeground);
    569 						else
    570 							StartFillCell(point, CellRows[point.Y][point.X].BackColor, m_MiddleMouseColor, m_MiddleMouseIsForeground);
    571 						this.Invalidate();
    572 					}
    573 					else
    574 						PaintCell(point, m_MiddleMouseColor, m_MiddleMouseIsForeground);
    575 					if (m_MiddleMouseIsForeground)
    576 						this.MostRecentForegroundColor = m_MiddleMouseColor;
    577 					break;
    578 				default:
    579 					break;
    580 			}
    581 		}
    582 
    583 		private bool m_DontRepaint = false;
    584 
    585 		/// <summary>
    586 		/// Gets or sets the DontRepaint = false.
    587 		/// </summary>
    588 		public bool DontRepaint 
    589 		{
    590 			get { return m_DontRepaint; }
    591 			set { m_DontRepaint = value; }
    592 		}
    593 
    594 		private void FillCell(Point point, byte origcolor, byte color, bool foreground)
    595 		{
    596 
    597 			Point curpoint = new Point();
    598 			if (foreground)
    599 			{
    600 				if (CellRows[point.Y][point.X].ForeColor == color)
    601 					return;
    602 				CellRows[point.Y][point.X].ForeColor = color;
    603 			}
    604 			else
    605 			{
    606 				if (CellRows[point.Y][point.X].BackColor == color)
    607 					return;
    608 				CellRows[point.Y][point.X].BackColor = color;
    609 			}
    610 
    611 
    612 
    613 			if (CurrentAction is PaintAction)
    614 			{
    615 				((PaintAction)CurrentAction).PaintedPoints.Add(point);
    616 			}
    617 		
    618 
    619 			RepaintSingleCell(point);
    620 			
    621 
    622 			if (point.Y - 1 >= 0) // up
    623 			{
    624 				curpoint.Y = point.Y - 1;
    625 				curpoint.X = point.X;
    626 				if (foreground)
    627 				{
    628 					if (CellRows[curpoint.Y][curpoint.X].ForeColor == origcolor)
    629 						FillCell(curpoint, origcolor, color, foreground);
    630 				}
    631 				else
    632 					if (CellRows[curpoint.Y][curpoint.X].BackColor == origcolor)
    633 						FillCell(curpoint, origcolor, color, foreground);
    634 			}
    635 			if ( point.X + 1 < m_Columns ) // right
    636 			{
    637 				curpoint.Y = point.Y;
    638 				curpoint.X = point.X + 1;
    639 				if (foreground)
    640 				{
    641 					if (CellRows[curpoint.Y][curpoint.X].ForeColor == origcolor)
    642 						FillCell(curpoint, origcolor, color, foreground);
    643 				}
    644 				else
    645 					if (CellRows[curpoint.Y][curpoint.X].BackColor == origcolor)
    646 						FillCell(curpoint, origcolor, color, foreground);
    647 			}
    648 
    649 			if (point.X - 1 >= 0) // left
    650 			{
    651 				curpoint.Y = point.Y;
    652 				curpoint.X = point.X - 1;
    653 				if (foreground)
    654 				{
    655 					if (CellRows[curpoint.Y][curpoint.X].ForeColor == origcolor)
    656 						FillCell(curpoint, origcolor, color, foreground);
    657 				}
    658 				else
    659 					if (CellRows[curpoint.Y][curpoint.X].BackColor == origcolor)
    660 						FillCell(curpoint, origcolor, color, foreground);
    661 			}
    662 			if (point.Y + 1 < m_Rows)	// down
    663 			{
    664 				curpoint.Y = point.Y + 1;
    665 				curpoint.X = point.X;
    666 				if (foreground)
    667 				{
    668 					if (CellRows[curpoint.Y][curpoint.X].ForeColor == origcolor)
    669 						FillCell(curpoint, origcolor, color, foreground);
    670 				}
    671 				else
    672 					if (CellRows[curpoint.Y][curpoint.X].BackColor == origcolor)
    673 						FillCell(curpoint, origcolor, color, foreground);
    674 			}
    675 
    676 			if ( m_Modified == false )
    677 				Modified = true;
    678 
    679 
    680 		}
    681 
    682 		private void PaintCell(Point point, byte color, bool foreground)
    683 		{
    684 			if (CurrentAction is PaintAction)
    685 			{
    686 				PaintAction act = (PaintAction)CurrentAction;
    687 				act.IsForeground = foreground;
    688 				act.NewPaintColor = color;
    689 				if (foreground)
    690 					act.OldPaintColor = CellRows[point.Y][point.X].ForeColor;
    691 				else
    692 					act.OldPaintColor = CellRows[point.Y][point.X].BackColor;
    693 				act.PaintedPoints.Add(new Point(point.X, point.Y));
    694 			}
    695 
    696 
    697 			if ( foreground )
    698 				CellRows[point.Y][point.X].ForeColor = color;
    699 			else
    700 				CellRows[point.Y][point.X].BackColor = color;
    701 			RepaintSingleCell(point);
    702 	
    703 			if (m_Modified == false)
    704 				Modified = true;
    705 
    706 
    707 		}
    708 
    709 		private void PaintCanvas_MouseMove(object sender, MouseEventArgs e)
    710 		{
    711 			if (e.Button != MouseButtons.None )
    712 			{
    713 				Point newpos = FindCellCoords(e.X, e.Y);
    714 				if ( newpos.X != SelectedCellPosition.X || newpos.Y != SelectedCellPosition.Y)
    715 				{
    716 					SelectAppropriateCell(e.X, e.Y);
    717 					if (m_PaintMode == PaintModes.Bold)
    718 					{
    719 						BoldSelectedCell();
    720 						RepaintSingleCell(newpos);
    721 					}
    722 					else if (m_PaintMode == PaintModes.Underline)
    723 					{
    724 						UnderlineSelectedCell();
    725 						RepaintSingleCell(newpos);
    726 					}
    727 					else if (m_PaintMode == PaintModes.RemoveFormatting)
    728 					{
    729 						RemoveFormattingSelectedCell();
    730 						RepaintSingleCell(newpos);
    731 					}
    732 					else if (CurrentAction is PaintAction)			
    733 					{
    734 						if (!((PaintAction)CurrentAction).PointExists(m_SelectedCellPosition))
    735 							PaintCellByMouseArgs(this.m_SelectedCellPosition, e);
    736 					}
    737 				}
    738 			}
    739 
    740 		}
    741 
    742 		private Point FindCellCoords(int x, int y)
    743 		{
    744 			// Find the cell we need to highlight.
    745 			int xpos = x / this.m_CellWidth;
    746 			int ypos = y / this.m_CellHeight;
    747 			if (xpos < 0)
    748 				xpos = 0;
    749 			if (ypos < 0)
    750 				ypos = 0;
    751 			if (ypos >= CellRows.Count)
    752 				ypos = CellRows.Count - 1;
    753 			if (xpos >= CellRows[ypos].Count)
    754 				xpos = CellRows[ypos].Count - 1;
    755 			return new Point(xpos, ypos);
    756 		}
    757 
    758 		private void SelectAppropriateCell(int x, int y)
    759 		{
    760 			Point oldpos = m_SelectedCellPosition;
    761 
    762 			SelectedCellPosition = FindCellCoords(x, y);
    763 			
    764 			RepaintSingleCell(oldpos); 
    765 			RepaintSingleCell(m_SelectedCellPosition); 
    766 		} 
    767 
    768 		private ColorPalette m_Colors = new ColorPalette(); 
    769 
    770 		/// <summary> 
    771 		/// Gets or sets the Colors.
    772 		/// </summary>
    773 		public ColorPalette Colors
    774 		{
    775 			get { return m_Colors; }
    776 			set { m_Colors = value; this.Invalidate(); }
    777 		}
    778 
    779 		public List<List<CellInfo>> CellRows;
    780 		 
    781 		private byte m_LeftMouseColor = 0;
    782 
    783 		/// <summary>
    784 		/// Gets or sets the LeftMouseColor .
    785 		/// </summary>
    786 		public byte LeftMouseColor 
    787 		{
    788 			get { return m_LeftMouseColor ; }
    789 			set { m_LeftMouseColor  = value; }
    790 		}
    791 
    792 		private byte m_MiddleMouseColor = 4;
    793 
    794 		/// <summary>
    795 		/// Gets or sets the MiddleMouseColor.
    796 		/// </summary>
    797 		public byte MiddleMouseColor
    798 		{
    799 			get { return m_MiddleMouseColor; }
    800 			set { m_MiddleMouseColor = value; }
    801 		}
    802 
    803 		private byte m_RightMouseColor = 1;
    804 
    805 		/// <summary>
    806 		/// Gets or sets the RightMouseColor.
    807 		/// </summary>
    808 		public byte RightMouseColor
    809 		{
    810 			get { return m_RightMouseColor; }
    811 			set { m_RightMouseColor = value; }
    812 		}
    813 		 
    814 		private bool m_LeftMouseIsForeground = true;
    815 
    816 		/// <summary>
    817 		/// Gets or sets the LeftMouseIsForeground.
    818 		/// </summary>
    819 		public bool LeftMouseIsForeground
    820 		{
    821 			get { return m_LeftMouseIsForeground; }
    822 			set { m_LeftMouseIsForeground = value; }
    823 		} 
    824 
    825 		private bool m_MiddleMouseIsForeground = false;
    826 
    827 		/// <summary>
    828 		/// Gets or sets the MiddleMouseIsForeground.
    829 		/// </summary>
    830 		public bool MiddleMouseIsForeground
    831 		{
    832 			get { return m_MiddleMouseIsForeground; }
    833 			set { m_MiddleMouseIsForeground = value; }
    834 		} 
    835 
    836 		private bool m_RightMouseIsForeground = false;
    837 
    838 		/// <summary>
    839 		/// Gets or sets the RightMouseIsForeground.
    840 		/// </summary>
    841 		public bool RightMouseIsForeground
    842 		{
    843 			get { return m_RightMouseIsForeground; }
    844 			set { m_RightMouseIsForeground = value; }
    845 		}
    846 
    847 		public CellInfo SelectedCell
    848 		{
    849 			get { return CellRows[m_SelectedCellPosition.Y][m_SelectedCellPosition.X]; }
    850 		}
    851 	
    852 
    853 		private void PaintCanvas_KeyPress(object sender, KeyPressEventArgs e)
    854 		{
    855 			e.Handled = true;
    856 			Point oldpos = m_SelectedCellPosition;
    857 			if (!char.IsControl((char)e.KeyChar) ) // && e.KeyChar != (char)Keys.Up && e.KeyChar != (char)Keys.Down && e.KeyChar != (char)Keys.Left && e.KeyChar != (char)Keys.Right && e.KeyChar != (char)Keys.Return)
    858 			{
    859 				AddCharacterChangeToKeypressAction(m_SelectedCellPosition.X, m_SelectedCellPosition.Y, SelectedCell.Character, (char)e.KeyChar);
    860 				SelectedCell.Character = (char)e.KeyChar;
    861 				SelectedCell.ForeColor = m_MostRecentForegroundColor;
    862 
    863 				if (m_SelectedCellPosition.X + 1 < m_Columns)
    864 					m_SelectedCellPosition.X++;
    865 				else
    866 				{
    867 					m_SelectedCellPosition.X = 0;
    868 					m_SelectedCellPosition.Y++;
    869 				}
    870 				RepaintSingleCell(oldpos);
    871 				RepaintSingleCell(m_SelectedCellPosition);
    872 
    873 			}
    874 			
    875 		}
    876 
    877 
    878 		private int ParseChar(char c)
    879 		{
    880 			return (int)(c - 0x30);
    881 		}
    882 
    883 		private const char ColorControl = '\x0003';
    884 		private const char UnderlineControl = '\x001F';
    885 		private const char BoldControl = '\x0002';
    886 		private const char PlainControl = '\x000F';
    887 		private const char ReverseControl = '\x0016';
    888 
    889 		internal void LoadStream(System.IO.Stream stream)
    890 		{
    891 
    892 			StreamReader reader = new StreamReader(stream);
    893 
    894 			CellRows.Clear();
    895 			CellRows = new List<List<CellInfo>>();
    896 
    897 
    898 			//int col = 0;
    899 			int row = 0;
    900 			while(reader.Peek() >= 0 )
    901 			{
    902 				int bc = 100;
    903 				int fc = 100;
    904 				CellRows.Add(new List<CellInfo>());
    905 				string strline = reader.ReadLine();
    906 				char[] str = strline.ToCharArray();
    907 				bool bold = false;
    908 				bool underlined = false;
    909 				for(int i = 0; i < str.Length; i++)
    910 				{
    911 					
    912 					if (IsControlCode(str[i]))
    913 					{
    914 						if (str[i] == BoldControl)
    915 						{
    916 							bold = (bold ? false : true);
    917 							continue;
    918 						}
    919 						else if (str[i] == UnderlineControl)
    920 						{
    921 							underlined = (underlined ? false : true);
    922 							continue;
    923 						}
    924 						else if (str[i] == ReverseControl)
    925 						{
    926 							continue;
    927 						}
    928 						else if (str[i] == PlainControl)
    929 						{
    930 							bold = false;
    931 							underlined = false;
    932 							continue;
    933 						}
    934 						else if (str[i] == ColorControl)
    935 						{
    936 							//bc = 100;
    937 							fc = 100;
    938 
    939 
    940 							if (i + 1 == str.Length)
    941 								break;
    942 							i++;
    943 
    944 							if (Char.IsDigit(str[i]))
    945 							{
    946 								// forecolor += str[i];
    947 								fc = ParseChar(str[i]);
    948 
    949 								if (i + 1 == str.Length)
    950 									break;
    951 								i++;
    952 								if (Char.IsDigit(str[i]))
    953 								{
    954 									fc = ((fc * 10)) + ParseChar(str[i]);
    955 
    956 									if (i + 1 == str.Length)
    957 										break;
    958 									i++;
    959 
    960 								}
    961 
    962 							}
    963 
    964 							if (fc > 15 && fc != 100)
    965 								fc = 0;
    966 
    967 							if (str[i] == ',')
    968 							{
    969 								if (++i == str.Length)
    970 									break;
    971 
    972 								if (Char.IsDigit(str[i]))
    973 								{
    974 									bc = ParseChar(str[i]);
    975 									if (++i == str.Length)
    976 										break;
    977 
    978 									if (Char.IsDigit(str[i]))
    979 									{
    980 										bc = (bc * 10) + ParseChar(str[i]);
    981 										if (++i == str.Length)
    982 											break;
    983 									}
    984 								}
    985 							}
    986 
    987 							if (bc > 15 && bc != 100)
    988 								bc = 1;
    989 
    990 
    991 							/*for (; i < str.Length && IsControlCode(str[i]); i++)
    992 							{
    993 							}
    994 							 */
    995 
    996 						}
    997 					}
    998 					CellInfo ci = new CellInfo();
    999 					ci.Character = str[i];
   1000 					if (fc != 100)
   1001 						ci.ForeColor = (byte)fc;
   1002 					if (bc != 100)
   1003 						ci.BackColor = (byte)bc;
   1004 					ci.Bold = bold;
   1005 					ci.Underlined = underlined;
   1006 					CellRows[row].Add(ci);
   1007 
   1008 
   1009 				}
   1010 				row++;
   1011 				
   1012 			}
   1013 
   1014 
   1015 			// find longest row.
   1016 			int longest = 0;
   1017 			foreach (List<CellInfo> cellrow in CellRows)
   1018 			{
   1019 				if (cellrow.Count > longest)
   1020 					longest = cellrow.Count;
   1021 			}
   1022 			this.m_Columns = longest;
   1023 			this.m_Rows = CellRows.Count;
   1024 			ResizeCellRows(); 
   1025 			ResizeByCellSize(); 
   1026 			PaintIntoBackground();
   1027 		}
   1028 
   1029 		private bool IsControlCode(char c)
   1030 		{
   1031 			return
   1032 				c == '\x0003' ||
   1033 				c == '\x001F' ||
   1034 				c == '\x0002' ||
   1035 				c == '\x000F' ||
   1036 				c == '\x0016';
   1037 		}
   1038 
   1039 		private void PaintCanvas_Load(object sender, EventArgs e)
   1040 		{
   1041 			this.Font = new Font(Program.Settings.PaintFontName, Program.Settings.PaintFontSize);
   1042 			this.CellHeight = Program.Settings.CellHeight;
   1043 			this.CellWidth = Program.Settings.CellWidth;
   1044 			this.HighlightColor = Program.Settings.HighlightColor;
   1045 			this.LeftMouseColor = Program.Settings.LMBColor;
   1046 			this.LeftMouseIsForeground = Program.Settings.LMBIsForeground;
   1047 			
   1048 			this.RightMouseColor = Program.Settings.RMBColor;
   1049 			this.RightMouseIsForeground = Program.Settings.RMBIsForeground;
   1050 			this.MiddleMouseColor = Program.Settings.MMBColor;
   1051 			this.MiddleMouseIsForeground = Program.Settings.MMBIsForeground;
   1052 			this.SeperatorColor = Program.Settings.SeperatorColor;
   1053 			this.HighlightColor = Program.Settings.HighlightColor;
   1054 
   1055 			if (this.RightMouseIsForeground)
   1056 				this.MostRecentForegroundColor = this.RightMouseColor;
   1057 			if (this.MiddleMouseIsForeground)
   1058 				this.MostRecentForegroundColor = this.MiddleMouseColor;
   1059 			if (this.LeftMouseIsForeground)
   1060 				this.MostRecentForegroundColor = this.LeftMouseColor;
   1061 			
   1062 		}
   1063 
   1064 		private byte m_MostRecentForegroundColor = 0;
   1065 
   1066 		/// <summary>
   1067 		/// Gets or sets the MostRecentForegroundColor.
   1068 		/// </summary>
   1069 		public byte MostRecentForegroundColor
   1070 		{
   1071 			get { return m_MostRecentForegroundColor; }
   1072 			set { m_MostRecentForegroundColor = value; }
   1073 		}
   1074 
   1075 		private void PaintCanvas_KeyDown(object sender, KeyEventArgs e)
   1076 		{
   1077 			
   1078 		}
   1079 
   1080 		public void ImportImage(string filename)
   1081 		{
   1082 			Bitmap bmp = new Bitmap(filename);
   1083 
   1084 			this.Columns = bmp.Width * 2;
   1085 			this.Rows = bmp.Height;
   1086 			for (int y = 0; y < bmp.Height; y++)
   1087 			{
   1088 				for (int x = 0; x < bmp.Width * 2; x++)
   1089 				{
   1090 					byte newcolor = this.Colors.FindClosestColor(bmp.GetPixel(x/2, y));
   1091 					this.CellRows[y][x++].BackColor = newcolor;
   1092 					this.CellRows[y][x].BackColor = newcolor;
   1093 				}
   1094 			}
   1095 			this.PaintIntoBackground();
   1096 			this.Invalidate();
   1097 		}
   1098 
   1099 		private void PaintCanvas_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
   1100 		{
   1101 			//e.Handled = true;
   1102 			bool repaint = false;
   1103 			Point oldpos = m_SelectedCellPosition;
   1104 
   1105 			if (e.KeyCode == Keys.Up)
   1106 			{
   1107 				if (m_SelectedCellPosition.Y > 0)
   1108 				{
   1109 					m_SelectedCellPosition.Y--;
   1110 				}
   1111 				repaint = true;
   1112 			}
   1113 			else if (e.KeyCode == Keys.Right)
   1114 			{
   1115 				if (m_SelectedCellPosition.X < CellRows[0].Count)
   1116 					m_SelectedCellPosition.X++;
   1117 				repaint = true;
   1118 			}
   1119 			else if (e.KeyCode == Keys.Down)
   1120 			{
   1121 				if (m_SelectedCellPosition.Y < CellRows.Count)
   1122 					m_SelectedCellPosition.Y++;
   1123 				repaint = true;
   1124 			}
   1125 			else if (e.KeyCode == Keys.Left)
   1126 			{
   1127 				if (m_SelectedCellPosition.X > 0)
   1128 					m_SelectedCellPosition.X--;
   1129 				repaint = true;
   1130 			}
   1131 			else if (e.KeyCode == Keys.Return)
   1132 			{
   1133 				if (m_SelectedCellPosition.Y < CellRows.Count)
   1134 					m_SelectedCellPosition.Y++;
   1135 				m_SelectedCellPosition.X = 0;
   1136 				repaint = true;
   1137 			}
   1138 			else if (e.KeyCode == Keys.Back)
   1139 			{
   1140 				if (m_SelectedCellPosition.X > 0)
   1141 					m_SelectedCellPosition.X--;
   1142 				AddCharacterChangeToKeypressAction(m_SelectedCellPosition.X, m_SelectedCellPosition.Y, SelectedCell.Character, ' ');
   1143 				SelectedCell.Character = ' ';
   1144 				
   1145 				repaint = true;
   1146 			}
   1147 			else if (e.KeyCode == Keys.Delete)
   1148 			{
   1149 				AddCharacterChangeToKeypressAction(m_SelectedCellPosition.X, m_SelectedCellPosition.Y, SelectedCell.Character, ' ');
   1150 				SelectedCell.Character = ' ';
   1151 				repaint = true;
   1152 			}
   1153 
   1154 			if (repaint)
   1155 			{
   1156 				RepaintSingleCell(oldpos);
   1157 				RepaintSingleCell(m_SelectedCellPosition);
   1158 			}
   1159 		}
   1160 
   1161 		public void AddCharacterChangeToKeypressAction(int x, int y, char origchar, char newchar)
   1162 		{
   1163 			if (CurrentAction == null)
   1164 			{
   1165 				CurrentAction = new KeypressAction();
   1166 				AddUndoAction(CurrentAction);
   1167 			}
   1168 
   1169 			if (CurrentAction is KeypressAction)
   1170 			{
   1171 				((KeypressAction)CurrentAction).AddCharacter(x, y, origchar, newchar);
   1172 			}
   1173 		}
   1174 
   1175 		public class UndoChangedEventArgs : EventArgs
   1176 		{
   1177 			public static readonly new UndoChangedEventArgs Empty = new UndoChangedEventArgs();
   1178 		}
   1179 
   1180 		public event EventHandler<UndoChangedEventArgs> UndoChanged;
   1181 
   1182 		protected virtual void OnUndoChanged(UndoChangedEventArgs e)
   1183 		{
   1184 			EventHandler<UndoChangedEventArgs> handler = UndoChanged;
   1185 			if (handler != null)
   1186 			{
   1187 				handler(this, e);
   1188 			}
   1189 		}
   1190 
   1191 		public class RedoChangedEventArgs : EventArgs
   1192 		{
   1193 			public static readonly new RedoChangedEventArgs Empty = new RedoChangedEventArgs();
   1194 		}
   1195 
   1196 		public event EventHandler<RedoChangedEventArgs> RedoChanged;
   1197 
   1198 		protected virtual void OnRedoChanged(RedoChangedEventArgs e)
   1199 		{
   1200 			EventHandler<RedoChangedEventArgs> handler = RedoChanged;
   1201 			if (handler != null)
   1202 			{
   1203 				handler(this, e);
   1204 			}
   1205 		}
   1206 
   1207 		public void AddUndoAction(IUndoableAction action)
   1208 		{
   1209 			UndoList.Push(action);
   1210 			if (RedoList.Count > 0)
   1211 			{
   1212 				RedoList.Clear();
   1213 				OnRedoChanged(RedoChangedEventArgs.Empty);
   1214 			}
   1215 			OnUndoChanged(UndoChangedEventArgs.Empty);
   1216 		}
   1217 
   1218 		public void AddRedoAction(IUndoableAction action)
   1219 		{
   1220 			RedoList.Push(action);
   1221 			OnRedoChanged(RedoChangedEventArgs.Empty);
   1222 		}
   1223 
   1224 		public void Undo()
   1225 		{
   1226 			if (UndoList.Count > 0)
   1227 			{
   1228 				IUndoableAction act = UndoList.Pop();
   1229 				act.Undo(this);
   1230 				OnUndoChanged(UndoChangedEventArgs.Empty);
   1231 				RedoList.Push(act);
   1232 				OnRedoChanged(RedoChangedEventArgs.Empty);
   1233 			}
   1234 		}
   1235 
   1236 		public void Redo()
   1237 		{
   1238 			if (RedoList.Count > 0)
   1239 			{
   1240 				IUndoableAction act = RedoList.Pop();
   1241 				act.Redo(this);
   1242 				OnRedoChanged(RedoChangedEventArgs.Empty);
   1243 				//UndoList.Clear();
   1244 				UndoList.Push(act);
   1245 				OnUndoChanged(UndoChangedEventArgs.Empty);
   1246 			}
   1247 		}
   1248 
   1249 		private void PaintCanvas_MouseUp(object sender, MouseEventArgs e)
   1250 		{
   1251 			if (CurrentAction is PaintAction)
   1252 			{
   1253 				AddUndoAction(CurrentAction);
   1254 				CurrentAction = null;
   1255 				
   1256 			}
   1257 		}
   1258 
   1259 		public void RepaintAll()
   1260 		{
   1261 			this.PaintIntoBackground();
   1262 			this.Invalidate();
   1263 		}
   1264 	}
   1265 }