--- /dev/null
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Diagnostics;\r
+using Cairo;\r
+using System.Text.RegularExpressions;\r
+using System.Xml.Serialization;\r
+using System.ComponentModel;\r
+using OpenTK.Input;\r
+\r
+namespace go\r
+{\r
+ [Serializable]\r
+ public class TextRun : GraphicObject\r
+ {\r
+ #region CTOR\r
+ public TextRun()\r
+ { \r
+\r
+ }\r
+ public TextRun(string _text)\r
+ : base()\r
+ {\r
+ Text = _text;\r
+ }\r
+ #endregion\r
+\r
+ //TODO:change protected to private\r
+ \r
+ #region private and protected fields\r
+ protected string _text = "label";\r
+ Alignment _textAlignment = Alignment.LeftCenter; \r
+ bool _multiline;\r
+ bool wordWrap;\r
+ protected Rectangle rText;\r
+ protected float widthRatio = 1f;\r
+ protected float heightRatio = 1f;\r
+ protected FontExtents fe;\r
+ protected TextExtents te;\r
+ #endregion\r
+\r
+\r
+ [XmlAttributeAttribute()][DefaultValue(Alignment.LeftCenter)]\r
+ public Alignment TextAlignment\r
+ {\r
+ get { return _textAlignment; }\r
+ set { _textAlignment = value; }\r
+ }\r
+ [XmlAttributeAttribute()][DefaultValue("label")]\r
+ public string Text\r
+ {\r
+ get { \r
+ return lines == null ? \r
+ _text : lines.Aggregate((i, j) => i + Interface.LineBreak + j);\r
+ }\r
+ set\r
+ {\r
+ if (_text == value)\r
+ return;\r
+ \r
+ registerForGraphicUpdate();\r
+ this.RegisterForLayouting ((int)LayoutingType.Sizing);\r
+\r
+\r
+ _text = value;\r
+\r
+ if (string.IsNullOrEmpty(_text))\r
+ _text = "";\r
+\r
+ lines = getLines;\r
+ }\r
+ }\r
+ [XmlAttributeAttribute()][DefaultValue(false)]\r
+ public bool Multiline\r
+ {\r
+ get { return _multiline; }\r
+ set\r
+ {\r
+ _multiline = value;\r
+ registerForGraphicUpdate();\r
+ }\r
+ }\r
+ [XmlAttributeAttribute()][DefaultValue(false)]\r
+ public bool WordWrap {\r
+ get {\r
+ return wordWrap;\r
+ }\r
+ set {\r
+ if (wordWrap == value)\r
+ return;\r
+ wordWrap = value;\r
+ registerForGraphicUpdate();\r
+ }\r
+ }\r
+\r
+ List<string> lines;\r
+ List<string> getLines {\r
+ get { \r
+ return _multiline ?\r
+ Regex.Split (_text, "\r\n|\r|\n").ToList() :\r
+ new List<string>(new string[] { _text });\r
+ }\r
+ }\r
+\r
+ #region GraphicObject overrides\r
+ [XmlAttributeAttribute()][DefaultValue(-1)]\r
+ public override int Width {\r
+ get { return base.Width; }\r
+ set { base.Width = value; }\r
+ }\r
+ [XmlAttributeAttribute()][DefaultValue(-1)]\r
+ public override int Height {\r
+ get { return base.Height; }\r
+ set { base.Height = value; }\r
+ }\r
+ [XmlAttributeAttribute()][DefaultValue(2)]\r
+ public override int Margin {\r
+ get { return base.Margin; }\r
+ set { base.Margin = value; }\r
+ }\r
+\r
+ protected override Size measureRawSize()\r
+ {\r
+ Size size;\r
+\r
+ if (lines == null)\r
+ lines = getLines;\r
+ \r
+ using (ImageSurface img = new ImageSurface (Format.Argb32, 10, 10)) {\r
+ using (Context gr = new Context (img)) {\r
+ //Cairo.FontFace cf = gr.GetContextFontFace ();\r
+\r
+ gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);\r
+ gr.SetFontSize (Font.Size);\r
+\r
+ te = new TextExtents();\r
+\r
+ foreach (string s in lines) {\r
+ string l = s.Replace("\t", new String (' ', Interface.TabSize));\r
+\r
+#if _WIN32 || _WIN64\r
+ TextExtents tmp = gr.TextExtents(str.ToUtf8());\r
+#elif __linux__\r
+ TextExtents tmp = gr.TextExtents (l);\r
+#endif\r
+ if (tmp.XAdvance > te.XAdvance)\r
+ te = tmp;\r
+ }\r
+ fe = gr.FontExtents;\r
+ int lc = lines.Count;\r
+ //ensure minimal height = text line height\r
+ if (lc == 0)\r
+ lc = 1; \r
+ size = new Size ((int)Math.Ceiling (te.XAdvance) + Margin * 2, (int)(fe.Height * lc) + Margin*2);\r
+ }\r
+ }\r
+\r
+ return size;;\r
+ }\r
+ protected override void onDraw (Context gr)\r
+ {\r
+ base.onDraw (gr);\r
+\r
+ gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);\r
+ gr.SetFontSize (Font.Size);\r
+\r
+ gr.Antialias = Antialias.Subpixel;\r
+ //gr.FontOptions.Antialias = Antialias.Subpixel;\r
+ //gr.FontOptions.HintMetrics = HintMetrics.On;\r
+\r
+ rText = new Rectangle(measureRawSize());\r
+ rText.Width -= 2 * Margin;\r
+ rText.Height -= 2 * Margin;\r
+\r
+ widthRatio = 1f;\r
+ heightRatio = 1f;\r
+\r
+ Rectangle cb = ClientRectangle;\r
+\r
+ //ignore text alignment if size to content = true\r
+ //or if text size is larger than client bounds\r
+ if (Bounds.Size < 0 || rText.Width > cb.Width)\r
+ {\r
+ rText.X = cb.X;\r
+ rText.Y = cb.Y;\r
+ }else {\r
+ \r
+ switch (TextAlignment)\r
+ {\r
+ case Alignment.None:\r
+ break;\r
+ case Alignment.TopLeft: //ok\r
+ rText.X = cb.X;\r
+ rText.Y = cb.Y;\r
+ break;\r
+ case Alignment.TopCenter: //ok\r
+ rText.Y = cb.Y;\r
+ rText.X = cb.X + cb.Width / 2 - rText.Width / 2;\r
+ break;\r
+ case Alignment.TopRight: //ok\r
+ rText.X = cb.Right - rText.Width;\r
+ rText.Y = cb.Y;\r
+ break;\r
+ case Alignment.TopStretch://ok\r
+ heightRatio = widthRatio = (float)cb.Width / rText.Width;\r
+ rText.X = cb.X;\r
+ rText.Y = cb.Y;\r
+ rText.Width = cb.Width;\r
+ rText.Height = (int)(rText.Height * heightRatio);\r
+ break;\r
+ case Alignment.LeftCenter://ok\r
+ rText.X = cb.X;\r
+ rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;\r
+ break;\r
+ case Alignment.LeftStretch://ok\r
+ heightRatio = widthRatio = (float)cb.Height / rText.Height;\r
+ rText.X = cb.X;\r
+ rText.Y = cb.Y;\r
+ rText.Height = cb.Height;\r
+ rText.Width = (int)(widthRatio * cb.Width);\r
+ break;\r
+ case Alignment.RightCenter://ok\r
+ rText.X = cb.X + cb.Width - rText.Width;\r
+ rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;\r
+ break;\r
+ case Alignment.RightStretch://ok\r
+ heightRatio = widthRatio = (float)cb.Height / rText.Height;\r
+ rText.Height = cb.Height;\r
+ rText.Width = (int)(widthRatio * cb.Width);\r
+ rText.X = cb.X;\r
+ rText.Y = cb.Y;\r
+ break;\r
+ case Alignment.BottomCenter://ok\r
+ rText.X = cb.Width / 2 - rText.Width / 2;\r
+ rText.Y = cb.Height - rText.Height;\r
+ break;\r
+ case Alignment.BottomStretch://ok\r
+ heightRatio = widthRatio = (float)cb.Width / rText.Width;\r
+ rText.Width = cb.Width;\r
+ rText.Height = (int)(rText.Height * heightRatio);\r
+ rText.Y = cb.Bottom - rText.Height;\r
+ rText.X = cb.X;\r
+ break;\r
+ case Alignment.BottomLeft://ok\r
+ rText.X = cb.X;\r
+ rText.Y = cb.Bottom - rText.Height;\r
+ break;\r
+ case Alignment.BottomRight://ok\r
+ rText.Y = cb.Bottom - rText.Height;\r
+ rText.X = cb.Right - rText.Width;\r
+ break;\r
+ case Alignment.Center://ok\r
+ rText.X = cb.X + cb.Width / 2 - rText.Width / 2;\r
+ rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;\r
+ break;\r
+ case Alignment.Fit://ok, peut être mieu aligné \r
+ widthRatio = (float)cb.Width / rText.Width;\r
+ heightRatio = (float)cb.Height / rText.Height;\r
+ rText = cb;\r
+ break;\r
+ case Alignment.HorizontalStretch://ok\r
+ heightRatio = widthRatio = (float)cb.Width / rText.Width;\r
+ rText.Width = cb.Width;\r
+ rText.Height = (int)(heightRatio * rText.Height);\r
+ rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;\r
+ rText.X = cb.X;\r
+ break;\r
+ case Alignment.VerticalStretch://ok\r
+ heightRatio = widthRatio = (float)cb.Height / rText.Height;\r
+ rText.Height = cb.Height;\r
+ rText.Width = (int)(widthRatio * rText.Width);\r
+ rText.X = cb.X + cb.Width / 2 - rText.Width / 2;\r
+ rText.Y = cb.Y;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+\r
+ gr.FontMatrix = new Matrix(widthRatio * Font.Size, 0, 0, heightRatio * Font.Size, 0, 0);\r
+\r
+\r
+ int curLineCount = 0;\r
+ for (int i = 0;i < lines.Count;i++) { \r
+ string l = lines [i].Replace ("\t", new String (' ', Interface.TabSize));\r
+ List<string> wl = new List<string> ();\r
+ int lineLength = (int)gr.TextExtents (l).XAdvance;\r
+\r
+ if (wordWrap && lineLength > cb.Width) {\r
+ string tmpLine = "";\r
+ int curChar = 0;\r
+ while (curChar < l.Length) {\r
+ tmpLine += l [curChar];\r
+ if ((int)gr.TextExtents (tmpLine).XAdvance > cb.Width) {\r
+ tmpLine = tmpLine.Remove (tmpLine.Length - 1);\r
+ wl.Add (tmpLine);\r
+ tmpLine = "";\r
+ continue;\r
+ }\r
+ curChar++;\r
+ }\r
+ wl.Add (tmpLine);\r
+ } else\r
+ wl.Add (l);\r
+\r
+ foreach (string ll in wl) {\r
+ lineLength = (int)gr.TextExtents (ll).XAdvance;\r
+ \r
+\r
+ if (string.IsNullOrWhiteSpace (ll)) {\r
+ curLineCount++;\r
+ continue;\r
+ }\r
+\r
+ gr.Color = Foreground; \r
+ gr.MoveTo (rText.X, rText.Y + fe.Ascent + fe.Height * curLineCount);\r
+\r
+ #if _WIN32 || _WIN64\r
+ gr.ShowText(ll.ToUtf8());\r
+ #elif __linux__\r
+ gr.ShowText (ll);\r
+ #endif\r
+ gr.Fill ();\r
+\r
+ curLineCount++;\r
+ \r
+ }\r
+ } \r
+ }\r
+ #endregion\r
+ }\r
+}\r