Procházet zdrojové kódy

Change to a multi-column based renderer

Bepis před 6 roky
rodič
revize
349ae3471c

+ 44 - 19
NTERA/Console/ConsoleRenderer.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Drawing;
+using System.Linq;
 using System.Windows.Forms;
 
 namespace NTERA.Console
@@ -9,7 +10,9 @@ namespace NTERA.Console
 	{
 		public int LineHeight = 16;
 
-		public List<IRenderItem> Items { get; protected set; } = new List<IRenderItem>();
+		public List<List<IRenderItem>> Items { get; protected set; } = new List<List<IRenderItem>>();
+
+		public List<Rectangle> UpdateRegions = new List<Rectangle>();
 		
 		public int offset;
 
@@ -18,9 +21,22 @@ namespace NTERA.Console
 		public delegate void AddedItemEventHandler(IRenderItem item);
 		public event AddedItemEventHandler AddedItem;
 
-		public void AddItem(IRenderItem item)
+		public ConsoleRenderer()
+		{
+			Items.Add(new List<IRenderItem>());
+		}
+
+		public void WriteItem(IRenderItem item)
+		{
+			Items[Items.Count - 1].Add(item);
+
+			AddedItem?.Invoke(item);
+		}
+
+		public void PrintItem(IRenderItem item)
 		{
-			Items.Add(item);
+			Items[Items.Count - 1].Add(item);
+			Items.Add(new List<IRenderItem>());
 
 			AddedItem?.Invoke(item);
 		}
@@ -32,12 +48,14 @@ namespace NTERA.Console
 			int screenLineCount = (int)Math.Ceiling(clientArea.Height / (float)LineHeight);
 
 			int firstItem = Math.Max(0, lastItem - screenLineCount);
-
+			
 			for (int i = firstItem; i < lastItem; i++)
 			{
+				int x = 0;
+
 				int y = clientArea.Height - (lastItem - i) * LineHeight;
 
-				var itemArea = new Rectangle(0, y, clientArea.Width, LineHeight);
+				var itemArea = new Rectangle(x, y, clientArea.Width - x, LineHeight);
 
 				if (!invalidateArea.IntersectsWith(itemArea))
 					continue;
@@ -46,7 +64,17 @@ namespace NTERA.Console
 				itemArea.Y -= LineHeight - itemArea.Height;
 				itemArea.Height = LineHeight;
 
-				Items[i].Render(graphics, itemArea, mousePointer);
+				foreach (var renderItem in Items[i].ToArray())
+				{
+					int newX = renderItem.Render(graphics, itemArea, invalidateArea, mousePointer);
+
+					itemArea.Width = newX - x;
+					itemArea.X = newX;
+
+					renderItem.Region = itemArea;
+
+					x = newX;
+				}
 			}
 
 			LastLineCount = screenLineCount;
@@ -54,25 +82,22 @@ namespace NTERA.Console
 		}
 
 
-		protected RectangleF? lastUpdateRange = null;
+		protected Rectangle? lastUpdateRange = null;
 
 		public void MouseHoverEvent(Point mousePoint, Control control)
 		{
-			foreach (var item in Items.ToArray())
+			foreach (var item in Items.SelectMany(x => x))
 			{
-				foreach (var rect in item.UpdateRegions)
+				if (!item.InvalidateOnMouseStateChange || !item.Region.Contains(mousePoint))
+					continue;
+
+				if (item.Region != lastUpdateRange)
 				{
-					if (!rect.Contains(mousePoint))
-						continue;
-
-					if (rect != lastUpdateRange)
-					{
-						control.Invalidate(Rectangle.Round(rect), true);
-						lastUpdateRange = rect;
-					}
-							
-					return;
+					control.Invalidate(item.Region, true);
+					lastUpdateRange = item.Region;
 				}
+							
+				return;
 			}
 
 			if (lastUpdateRange != null)

+ 13 - 15
NTERA/Console/EraConsoleInstance.cs

@@ -16,22 +16,19 @@ namespace NTERA.Console
 
 		public Color ForeColor = Color.White;
 
-		public void AddText(string text)
+		public void AddText(string text, Color? color = null, bool print = true)
 		{
-			var item = new TextRenderItem(text, Alignment)
+			var item = new TextRenderItem(text)
 			{
-				TextBrush = new SolidBrush(ForeColor)
+				TextBrush = new SolidBrush(color ?? ForeColor),
+				Alignment = Alignment
 			};
 
-			Renderer.AddItem(item);
-		}
-
-		public void AddText(string text, Color color)
-		{
-			var item = new TextRenderItem(text);
-			item.TextBrush = new SolidBrush(color);
 
-			Renderer.AddItem(item);
+			if (print)
+				Renderer.PrintItem(item);
+			else
+				Renderer.WriteItem(item);
 		}
 
 
@@ -128,7 +125,7 @@ namespace NTERA.Console
 
 		public void PrintSingleLine(string line, bool temporary = false)
 		{
-			AddText(line);
+			AddText(line, print: true);
 		}
 
 		public void RefreshStrings(bool something)
@@ -152,7 +149,8 @@ namespace NTERA.Console
 		public void Write(string message)
 		{
 			//message.Replace(' ', ' ');
-			bodyBuilder.Append(message);
+			//bodyBuilder.Append(message);
+			AddText(message, print: false);
 		}
 
 		public void NewLine()
@@ -237,14 +235,14 @@ namespace NTERA.Console
 		public void PrintHtml(string html, bool newline)
 		{
 			foreach (var item in HtmlParser.ParseHtml(html))
-				Renderer.AddItem(item);
+				Renderer.PrintItem(item);
 		}
 
 		public void PrintImg(string img)
 		{
 			var image = AppContents.GetContent<CroppedImage>(img);
 
-			Renderer.AddItem(new ImageRenderItem(image.BaseImage.Bitmap, image.Rectangle, alignment: Alignment));
+			Renderer.WriteItem(new ImageRenderItem(image.BaseImage.Bitmap, image.Rectangle, alignment: Alignment));
 		}
 
 		public void PrintShape(string shape, int[] param)

+ 4 - 2
NTERA/Console/IRenderItem.cs

@@ -5,8 +5,10 @@ namespace NTERA.Console
 {
 	public interface IRenderItem : IDisposable
 	{
-		Rectangle[] UpdateRegions { get; }
+		bool InvalidateOnMouseStateChange { get; }
 
-		void Render(Graphics graphics, Rectangle renderArea, Point mousePointer);
+		Rectangle Region { get; set; }
+
+		int Render(Graphics graphics, Rectangle renderArea, Rectangle invalidatedArea, Point mousePointer);
 	}
 }

+ 4 - 2
NTERA/Console/RenderItem/BaseRenderItem.cs

@@ -4,9 +4,11 @@ namespace NTERA.Console
 {
 	public abstract class BaseRenderItem : IRenderItem
 	{
-		public Rectangle[] UpdateRegions { get; protected set; } = { };
+		public virtual bool InvalidateOnMouseStateChange { get; protected set; }
 
-		public abstract void Render(Graphics graphics, Rectangle renderArea, Point mousePointer);
+		public Rectangle Region { get; set; }
+
+		public abstract int Render(Graphics graphics, Rectangle renderArea, Rectangle invalidatedArea, Point mousePointer);
 
 		public virtual void Dispose() { }
 	}

+ 10 - 21
NTERA/Console/RenderItem/ButtonTextRenderItem.cs

@@ -1,5 +1,6 @@
 using System.Drawing;
 using System.Linq;
+using System.Windows.Forms;
 
 namespace NTERA.Console
 {
@@ -9,38 +10,26 @@ namespace NTERA.Console
 
 		public static SolidBrush TextBrush = new SolidBrush(Color.White);
 
-		public static SolidBrush BackingHighlightBrush = new SolidBrush(Color.DarkRed);
-
-		public static SolidBrush SelectedBackingHighlightBrush = new SolidBrush(Color.Yellow);
+		public static SolidBrush SelectedBrush = new SolidBrush(Color.Yellow);
 
 		public string Text { get; set; }
 
-		public CharacterRange[] ButtonRanges { get; set; }
+		public override bool InvalidateOnMouseStateChange => true;
 
-		public ButtonTextRenderItem(string text, CharacterRange[] buttonRanges)
+		public ButtonTextRenderItem(string text)
 		{
-			Text = text;
-			ButtonRanges = buttonRanges;
+			Text = text.Replace(" ", "  ");
 		}
 
-		public override void Render(Graphics graphics, Rectangle renderArea, Point mousePointer)
+		public override int Render(Graphics graphics, Rectangle renderArea, Rectangle invalidatedArea, Point mousePointer)
 		{
-			StringFormat stringFormat1 = new StringFormat();
-			stringFormat1.SetMeasurableCharacterRanges(ButtonRanges);
-
-			UpdateRegions = graphics.MeasureCharacterRanges(Text, Font, renderArea, stringFormat1)
-				.Select(x => Rectangle.Round(x.GetBounds(graphics))).ToArray();
+			//graphics.DrawString(Text, Font, TextBrush, renderArea);
 
-			foreach (var region in UpdateRegions)
-			{
-				Brush brush = region.Contains(mousePointer)
-					? SelectedBackingHighlightBrush
-					: BackingHighlightBrush;
+			//return (int)graphics.MeasureString(Text, Font).Width + renderArea.X;
 
-				graphics.FillRectangle(brush, region);
-			}
+			TextRenderer.DrawText(graphics, Text, Font, renderArea.Location, TextBrush.Color, TextFormatFlags.ExternalLeading);
 
-			graphics.DrawString(Text, Font, TextBrush, renderArea);
+			return TextRenderer.MeasureText(graphics, Text, Font).Width + renderArea.X;
 		}
 	}
 }

+ 13 - 3
NTERA/Console/RenderItem/ImageRenderItem.cs

@@ -31,7 +31,7 @@ namespace NTERA.Console
 			Alignment = alignment;
 		}
 
-		public override void Render(Graphics graphics, Rectangle renderArea, Point mousePointer)
+		public override int Render(Graphics graphics, Rectangle renderArea, Rectangle invalidatedArea, Point mousePointer)
 		{
 			int x;
 
@@ -39,7 +39,7 @@ namespace NTERA.Console
 			{
 				default:
 				case DisplayLineAlignment.LEFT:
-					x = 0;
+					x = renderArea.X;
 					break;
 				case DisplayLineAlignment.CENTER:
 					x = (renderArea.Width - Image.Width) / 2;
@@ -49,7 +49,12 @@ namespace NTERA.Console
 					break;
 			}
 
-			graphics.DrawImage(Image, new Rectangle(x, renderArea.Y, Image.Width, renderArea.Height));
+			float ratio = Image.Width / (float)Image.Height;
+			int width = (int)(ratio * renderArea.Height);
+
+			graphics.DrawImage(Image, new Rectangle(x, renderArea.Y, width, renderArea.Height));
+
+			return x + width;
 		}
 
 		public static List<ImageRenderItem> CreateFromLargeBitmap(Bitmap original, int lineHeight)
@@ -74,5 +79,10 @@ namespace NTERA.Console
 
 			return items;
 		}
+
+		public override void Dispose()
+		{
+			Image?.Dispose();
+		}
 	}
 }

+ 28 - 6
NTERA/Console/RenderItem/TextRenderItem.cs

@@ -1,6 +1,8 @@
 using System;
 using System.Collections.Generic;
 using System.Drawing;
+using System.Linq;
+using System.Windows.Forms;
 using NTERA.Interop;
 
 namespace NTERA.Console
@@ -9,16 +11,28 @@ namespace NTERA.Console
 	{
 		public Font Font { get; set; } = new Font("MS UI Gothic", 12);
 
-		public SolidBrush TextBrush = new SolidBrush(Color.White);
+		public SolidBrush TextBrush { get; set; } = new SolidBrush(Color.White);
 
 		public string Text { get; set; }
 
-		public DisplayLineAlignment Alignment;
+		public DisplayLineAlignment Alignment { get; set; }
+
+		private static readonly string[] FullwidthCharacters = "0123456789。".ToCharArray().Select(x => x.ToString()).ToArray();
+
+		private static string AlignText(string input)
+		{
+			foreach (var num in FullwidthCharacters)
+			{
+				input = input.Replace(num, $" {num}");
+			}
+
+			return input.Replace(" ", "    ");
+		}
 
 
 		public TextRenderItem(string text, DisplayLineAlignment alignment = DisplayLineAlignment.LEFT, Color? color = null)
 		{
-			Text = text;
+			Text = AlignText(text); //text.Replace(" ", "    ").Replace("6", " 6"); //" 6   ", " 6  "
 			Alignment = alignment;
 			
 			if (color.HasValue)
@@ -26,7 +40,7 @@ namespace NTERA.Console
 		}
 		
 
-		public override void Render(Graphics graphics, Rectangle renderArea, Point mousePointer)
+		public override int Render(Graphics graphics, Rectangle renderArea, Rectangle invalidatedArea, Point mousePointer)
 		{
 			int width = (int)graphics.MeasureString(Text, Font).Width;
 
@@ -36,7 +50,7 @@ namespace NTERA.Console
 			{
 				default:
 				case DisplayLineAlignment.LEFT:
-					x = 0;
+					x = renderArea.X;
 					break;
 				case DisplayLineAlignment.CENTER:
 					x = (renderArea.Width - width) / 2;
@@ -46,7 +60,15 @@ namespace NTERA.Console
 					break;
 			}
 
-			graphics.DrawString(Text, Font, TextBrush, x, renderArea.Y);
+			//graphics.DrawString(Text, Font, TextBrush, x, renderArea.Y);
+
+			//return x + width;
+
+			var point = new Point(x, renderArea.Y);
+
+			TextRenderer.DrawText(graphics, Text, Font, point, TextBrush.Color, TextFormatFlags.ExpandTabs);
+
+			return TextRenderer.MeasureText(graphics, Text, Font).Width + renderArea.X;
 		}
 
 		public static List<TextRenderItem> CreateFromLinedText(string text)