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 }