2 * Copyright (C) 2013 FooProject
3 * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
6 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
7 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
9 You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
12 using System.Collections.Generic;
15 using System.Windows.Controls;
16 using System.Windows.Media;
17 using System.Windows.Media.TextFormatting;
19 namespace FooEditEngine.WPF
21 sealed class WPFRender : IPrintableTextRender, IDisposable
24 double _FontSize, _LineHeight;
25 DrawingContext Context;
29 System.Windows.Media.Color ForegroundColor, BackgroundColor, HilightColor, Keyword1Color, Keyword2Color, LiteralColor, UrlColor, ControlCharColor, CommentColor, InsertCaretColor, OverwriteCaretColor, LineMarkerColor;
30 BrushStockes Brushes = new BrushStockes();
31 PenStockes Pens = new PenStockes();
35 public WPFRender(FontFamily font, double fontSize)
37 this.ChangedRenderResource += (s, e) => { };
38 this.ChangedRightToLeft += (s, e) => { };
39 this.FontFamily = font;
40 this.FontSize = fontSize;
43 public WPFRender(FooTextBox textbox, double width, double height,FrameworkElement image)
45 this.ChangedRenderResource += (s, e) => { };
46 this.ChangedRightToLeft += (s, e) => { };
48 this.FontFamily = textbox.FontFamily;
49 this.FontSize = textbox.FontSize;
50 this.ForegroundColor = textbox.Foreground;
51 this.BackgroundColor = textbox.Background;
52 this.ControlCharColor = textbox.ControlChar;
53 this.HilightColor = textbox.Hilight;
54 this.CommentColor = textbox.Comment;
55 this.UrlColor = textbox.URL;
56 this.Keyword1Color = textbox.Keyword1;
57 this.Keyword2Color = textbox.Keyword2;
58 this.LiteralColor = textbox.Literal;
59 this.InsertCaretColor = textbox.InsertCaret;
60 this.OverwriteCaretColor = textbox.OverwriteCaret;
61 this.LineMarkerColor = textbox.LineMarker;
63 this.host = (VisualHost)image;
66 public event EventHandler ChangedRightToLeft;
68 public TextAntialiasMode TextAntialiasMode
74 public bool ShowFullSpace
80 public bool ShowHalfSpace
92 public bool RightToLeft
94 get { return this._RightToLeft; }
97 this._RightToLeft = value;
98 this.ChangedRightToLeft(this, null);
102 public bool InsertMode
108 public Rectangle TextArea
114 public FontFamily FontFamily
123 this.ChangedRenderResource(this, new ChangedRenderRsourceEventArgs(ResourceType.Font));
127 public double FontSize
131 return this._FontSize;
135 this._FontSize = value;
137 TextLayout layout = new TextLayout("0", this.FontFamily, this.FontSize, Brushes[this.Foreground], 0);
138 this.LineNemberWidth = layout.Lines[0].Width * EditView.LineNumberLength;
139 this._LineHeight = layout.Lines[0].Height;
140 this.emSize = new Size(layout.Lines[0].Width, layout.Lines[0].Height);
143 this.ChangedRenderResource(this, new ChangedRenderRsourceEventArgs(ResourceType.Font));
147 public double LineNemberWidth
153 public double FoldingWidth
161 public int TabWidthChar
165 return this._TabWidthChar;
169 TextLayout layout = new TextLayout("a", this.FontFamily, this.FontSize, this.Brushes[this.ForegroundColor], 0);
170 double width = layout.Lines[0].WidthIncludingTrailingWhitespace;
172 this.TabWidth = width * value;
173 this._TabWidthChar = value;
183 public System.Windows.Media.Color Foreground
187 return this.ForegroundColor;
191 this.ForegroundColor = value;
192 this.ChangedRenderResource(this, new ChangedRenderRsourceEventArgs(ResourceType.Brush));
196 public System.Windows.Media.Color Background
200 return this.BackgroundColor;
204 this.BackgroundColor = value;
205 this.ChangedRenderResource(this, new ChangedRenderRsourceEventArgs(ResourceType.Brush));
209 public System.Windows.Media.Color InsertCaret
213 return this.InsertCaretColor;
217 this.InsertCaretColor = value;
221 public System.Windows.Media.Color OverwriteCaret
225 return this.OverwriteCaretColor;
229 this.OverwriteCaretColor = value;
233 public System.Windows.Media.Color LineMarker
237 return this.LineMarkerColor;
241 this.LineMarkerColor = value;
245 public System.Windows.Media.Color ControlChar
249 return this.ControlCharColor;
253 this.ControlCharColor = value;
254 this.ChangedRenderResource(this, new ChangedRenderRsourceEventArgs(ResourceType.Brush));
258 public System.Windows.Media.Color Url
262 return this.UrlColor;
266 this.UrlColor = value;
267 this.ChangedRenderResource(this, new ChangedRenderRsourceEventArgs(ResourceType.Brush));
271 public System.Windows.Media.Color Hilight
275 return this.HilightColor;
279 this.HilightColor = value;
280 this.ChangedRenderResource(this, new ChangedRenderRsourceEventArgs(ResourceType.Brush));
284 public System.Windows.Media.Color Comment
288 return this.CommentColor;
292 this.CommentColor = value;
293 this.ChangedRenderResource(this, new ChangedRenderRsourceEventArgs(ResourceType.Brush));
297 public System.Windows.Media.Color Literal
301 return this.LiteralColor;
305 this.LiteralColor = value;
306 this.ChangedRenderResource(this, new ChangedRenderRsourceEventArgs(ResourceType.Brush));
310 public System.Windows.Media.Color Keyword1
314 return this.Keyword1Color;
318 this.Keyword1Color = value;
319 this.ChangedRenderResource(this, new ChangedRenderRsourceEventArgs(ResourceType.Brush));
323 public System.Windows.Media.Color Keyword2
327 return this.Keyword2Color;
331 this.Keyword2Color = value;
332 this.ChangedRenderResource(this, new ChangedRenderRsourceEventArgs(ResourceType.Brush));
336 public float HeaderHeight
338 get { return (float)this._LineHeight; }
341 public float FooterHeight
343 get { return (float)this._LineHeight; }
352 public bool ShowLineBreak
356 throw new NotImplementedException();
361 throw new NotImplementedException();
365 public event ChangedRenderResourceEventHandler ChangedRenderResource;
367 public void DrawCachedBitmap(Rectangle rect)
372 public void CacheContent()
377 public bool IsVaildCache()
382 public void SetDrawingContext(DrawingContext dc)
387 public void BegineDraw()
389 this.visual = new DrawingVisual();
390 this.Context = this.visual.RenderOpen();
393 public void EndDraw()
395 this.Context.Close();
396 this.host.AddVisual(this.visual);
399 public bool Resize(double width, double height)
404 public void DrawString(string str, double x, double y, StringAlignment align, Size layoutRect, StringColorType colorType = StringColorType.Forground)
406 TextAlignment TextAlign = TextAlignment.Left;
409 case StringAlignment.Left:
410 TextAlign = TextAlignment.Left;
412 case StringAlignment.Center:
413 TextAlign = TextAlignment.Center;
415 case StringAlignment.Right:
416 TextAlign = TextAlignment.Right;
419 TextLayout layout = new TextLayout(str, this.FontFamily, this.FontSize, this.Brushes[this.ForegroundColor], layoutRect.Width, TextAlign);
420 layout.FlowDirection = this.RightToLeft ? FlowDirection.RightToLeft : FlowDirection.LeftToRight;
421 layout.Draw(this.Context, x, y);
425 public void FillRectangle(Rectangle rect,FillRectType type)
431 case FillRectType.OverwriteCaret:
432 this.Context.DrawRectangle(this.Brushes[this.OverwriteCaret], null, rect);
434 case FillRectType.InsertCaret:
435 this.Context.DrawRectangle(this.Brushes[this.InsertCaret], null, rect);
437 case FillRectType.InsertPoint:
439 case FillRectType.LineMarker:
440 this.Context.DrawRectangle(this.Brushes[this.LineMarker], null, rect);
445 public void DrawFoldingMark(bool expand, double x, double y)
447 string str = expand ? "-" : "+";
448 TextLayout layout = new TextLayout(str, this.FontFamily, this.FontSize, this.Brushes[this.ForegroundColor], this.FoldingWidth);
449 layout.Draw(this.Context, x, y);
452 public void DrawLine(Point from, Point to)
454 Brush brush = this.Brushes[this.ForegroundColor];
455 Pen pen = this.Pens.Get(brush,HilightType.Sold);
456 this.Context.DrawLine(pen, from, to);
459 public void FillBackground(Rectangle rect)
463 this.Context.DrawRectangle(this.Brushes[this.Background], null, rect);
466 public void DrawOneLine(LineToIndexTable lti, int row, double x, double y, IEnumerable<Selection> SelectRanges)
468 TextLayout layout = (TextLayout)lti.GetLayout(row);
470 if (lti.GetLengthFromLineNumber(row) == 0)
473 if (this.Printing == false)
475 foreach (Selection sel in SelectRanges)
477 if (sel.length == 0 || sel.start == -1)
480 foreach (TextBounds bound in layout.GetTextBounds(sel.start, sel.length))
482 Rect rect = new Rect(x,y,bound.Rectangle.Width,bound.Rectangle.Height);
483 this.Context.DrawRectangle(this.Brushes[this.Hilight], null, rect);
488 layout.Draw(this.Context, x, y);
491 public List<LineToIndexTableData> BreakLine(Document doc, LineToIndexTable layoutLineCollection, int startIndex, int endIndex, double wrapwidth)
493 List<LineToIndexTableData> output = new List<LineToIndexTableData>();
495 foreach (string str in doc.GetLines(startIndex, endIndex))
497 TextLayout layout = new TextLayout(str, this.FontFamily, this.FontSize, this.Brushes[this.Foreground], wrapwidth);
500 foreach (TextLine line in layout.Lines)
502 if (line.Length == 0 && line.NewlineLength == 0)
505 int length = line.Length;
507 IList<TextSpan<TextRun>> runs = line.GetTextRunSpans();
508 if (runs.Last().Value is TextEndOfParagraph)
511 bool lineend = false;
512 if (line.NewlineLength > 0)
515 output.Add(layoutLineCollection.CreateLineToIndexTableData(i, length, lineend, null));
521 startIndex += str.Length;
524 if (output.Count > 0)
525 output.Last().LineEnd = true;
530 public ITextLayout CreateLaytout(string str, SyntaxInfo[] syntaxCollection, IEnumerable<Marker> MarkerRanges)
532 TextLayout layout = new TextLayout(str,this.FontFamily,this.FontSize,Brushes[this.Foreground],this.TextArea.Width);
533 layout.TextWarpping = TextWrapping.NoWrap;
534 layout.FlowDirection = this.RightToLeft ? FlowDirection.RightToLeft : FlowDirection.LeftToRight;
536 if (syntaxCollection != null)
538 foreach (SyntaxInfo s in syntaxCollection)
540 Brush brush = this.Brushes[this.Foreground];
543 case TokenType.Comment:
544 brush = this.Brushes[this.Comment];
546 case TokenType.Keyword1:
547 brush = this.Brushes[this.Keyword1];
549 case TokenType.Keyword2:
550 brush = this.Brushes[this.Keyword2];
552 case TokenType.Literal:
553 brush = this.Brushes[this.Literal];
556 TextEffect effect = new TextEffect(null, brush, null, s.index, s.length);
558 layout.SetTextEffect(effect);
562 if (MarkerRanges != null)
564 foreach (Marker m in MarkerRanges)
566 if (m.start == -1 || m.length == 0)
570 if (m.hilight == HilightType.Url)
572 brush = this.Brushes[this.Url];
573 TextEffect effect = new TextEffect(null, brush, null, m.start, m.length);
575 layout.SetTextEffect(effect);
579 System.Windows.Media.Color color = new System.Windows.Media.Color();
584 brush = this.Brushes[color];
587 Pen pen = this.Pens.Get(brush,m.hilight);
589 TextDecorationCollection collection = new TextDecorationCollection();
590 TextDecoration decoration = new TextDecoration();
591 decoration.Pen = pen;
592 decoration.Location = TextDecorationLocation.Underline;
594 collection.Add(decoration);
596 if (m.hilight == HilightType.Squiggle)
597 layout.SetSquilleLine(m.start, m.length, collection);
599 layout.SetTextDecoration(m.start, m.length, collection);
606 public void DrawGripper(Point p, double radius)
608 //タッチには対応していないので実装する必要はない
609 throw new NotImplementedException();
612 public void Dispose()
621 ResourceManager<System.Windows.Media.Color, Brush> collection = new ResourceManager<System.Windows.Media.Color, Brush>();
622 public Brush this[System.Windows.Media.Color c]
627 if (this.collection.TryGetValue(c, out brush))
629 brush = new SolidColorBrush(c);
631 this.collection.Add(c, brush);
639 ResourceManager<Brush, ResourceManager<HilightType, Pen>> cache = new ResourceManager<Brush, ResourceManager<HilightType, Pen>>();
640 public Pen Get(Brush brush, HilightType type)
642 ResourceManager<HilightType, Pen> hilights;
644 if (this.cache.TryGetValue(brush, out hilights))
646 if (hilights.TryGetValue(type, out effect))
648 effect = CreatePen(brush,type);
649 hilights.Add(type, effect);
652 effect = CreatePen(brush, type);
653 hilights = new ResourceManager<HilightType, Pen>();
654 hilights.Add(type, effect);
655 this.cache.Add(brush, hilights);
658 Pen CreatePen(Brush brush, HilightType type)
660 Pen pen = new Pen(brush, 1.0f);
663 case HilightType.Sold:
664 case HilightType.Url:
665 case HilightType.Squiggle:
666 pen.DashStyle = DashStyles.Solid;
668 case HilightType.Dash:
669 pen.DashStyle = DashStyles.Dash;
671 case HilightType.DashDot:
672 pen.DashStyle = DashStyles.DashDot;
674 case HilightType.DashDotDot:
675 pen.DashStyle = DashStyles.DashDotDot;
677 case HilightType.Dot:
678 pen.DashStyle = DashStyles.Dot;