using System.ComponentModel;
using System.Threading.Tasks;
using System.Collections;
+using System.Collections.Generic;
namespace Crow {
public abstract class CommandBase : IValueChange {
#region CTOR
protected CommandBase() {}
- protected CommandBase (string _caption, string _icon)
+ protected CommandBase (string _caption, string _icon = null)
{
caption = _caption;
icon = _icon;
NotifyValueChanged ("Caption", caption);
}
}
- public class CommandGroup : CommandBase, IEnumerable
+ public class CommandGroup : CommandBase, IEnumerable, IList<CommandBase>
{
public ObservableList<CommandBase> Commands = new ObservableList<CommandBase>();
base (caption, icon) {
Commands.AddRange (commands);
}
+ public CommandGroup (string caption, params CommandBase[] commands) :
+ base (caption) {
+ Commands.AddRange (commands);
+ }
public CommandGroup (params CommandBase[] commands) {
Commands.AddRange (commands);
}
+
+ public int Count => Commands.Count;
+
+ public bool IsReadOnly => false;
+
+ public CommandBase this[int index] { get => Commands[index]; set => Commands[index] = value; }
+
public IEnumerator GetEnumerator() => Commands.GetEnumerator ();
+
+ public int IndexOf(CommandBase item) => Commands.IndexOf (item);
+
+ public void Insert(int index, CommandBase item) => Commands.Insert(index, item);
+
+ public void RemoveAt(int index) => Commands.RemoveAt(index);
+
+ public void Add(CommandBase item) => Commands.Add (item);
+
+ public void Clear() => Commands.Clear();
+
+ public bool Contains(CommandBase item) => Commands.Contains (item);
+
+ public void CopyTo(CommandBase[] array, int arrayIndex) => Commands.CopyTo (array, arrayIndex);
+
+ public bool Remove(CommandBase item) {
+ Commands.Remove (item);
+ return true;
+ }
+
+ IEnumerator<CommandBase> IEnumerable<CommandBase>.GetEnumerator()
+ => Commands.GetEnumerator();
}
case DbgEvtType.Update:
return Colors.Grey;
case DbgEvtType.IFaceLoad:
- return Colors.Teal;
+ return Colors.Teal;
default:
+ if (type.HasFlag(DbgEvtType.Mouse))
+ return Colors.DeepPink;
return Colors.White;
}
}
Override = 0x020000,
TemplatedGroup = 0x010000,
Dispose = 0x008000,
+ Mouse = 0x004000,
Update = IFace | 0x004000,
ProcessLayouting = IFace | Update | Lock | Layouting,
ProcessDrawing = IFace | Update | Lock | Drawing,
IFaceLoad = IFace | 0x01,
IFaceInit = IFace | 0x02,
- CreateITor = IFace | 0x04,
- IFaceReloadTheme = IFace | 0x08,
+ CreateITor = IFace | 0x03,
+ IFaceReloadTheme = IFace | 0x04,
HoverWidget = Focus | Widget | 0x01,
FocusedWidget = Focus | Widget | 0x02,
//10 nth bit set for graphic obj
GOClassCreation = Widget | 0x01,
GOInitialization = Widget | 0x02,
- GORegisterForGraphicUpdate = Widget | 0x04,
- GOEnqueueForRepaint = Widget | 0x08,
- GONewDataSource = Widget | 0x10,
- GONewParent = Widget | 0x20,
- GONewLogicalParent = Widget | 0x40,
- GOAddChild = Widget | 0x80,
+ GORegisterForGraphicUpdate = Widget | 0x03,
+ GOEnqueueForRepaint = Widget | 0x04,
+ GONewDataSource = Widget | 0x05,
+ GONewParent = Widget | 0x06,
+ GONewLogicalParent = Widget | 0x07,
+ GOAddChild = Widget | 0x08,
- GOSearchLargestChild = Widget | 0x09,
- GOSearchTallestChild = Widget | 0x0A,
- GORegisterForRedraw = Widget | 0x0B,
- GOComputeChildrenPositions = Widget | 0x0C,
- GOOnChildLayoutChange = Widget | 0x0D,
+ GOMeasure = Widget | 0x09,
+ GOSearchLargestChild = Widget | 0x0A,
+ GOSearchTallestChild = Widget | 0x0B,
+ GORegisterForRedraw = Widget | 0x0C,
+ GOComputeChildrenPositions = Widget | 0x0D,
+ GOOnChildLayoutChange = Widget | 0x0E,
- AlreadyDisposed = Dispose | Widget | Error | 0x01,
- DisposedByGC = Dispose | Widget | Error | 0x02,
- Disposing = Dispose | Widget | 0x01,
+ AlreadyDisposed = Widget | Dispose | Error | 0x01,
+ DisposedByGC = Widget | Dispose | Error | 0x02,
+ Disposing = Widget | Dispose | 0x01,
- GOClippingRegistration = Clipping | Widget | 0x01,
- GORegisterClip = Clipping | Widget | 0x02,
- GORegisterLayouting = Layouting | Widget | 0x01,
- GOProcessLayouting = Layouting | Widget | 0x02,
- GOProcessLayoutingWithNoParent = Layouting | Widget | Warning | 0x01,
- GOMeasure = Widget | 0x03,
- GODraw = Drawing | Widget | 0x01,
- GORecreateCache = Drawing | Widget | 0x02,
- GOUpdateCache = Drawing | Widget | 0x03,
- GOPaint = Drawing | Widget | 0x04,
+ GOClippingRegistration = Widget | Clipping | 0x01,
+ GORegisterClip = Widget | Clipping | 0x02,
+ GORegisterLayouting = Widget | Layouting | 0x01,
+ GOProcessLayouting = Widget | Layouting | 0x02,
+ GOProcessLayoutingWithNoParent = Widget | Layouting | Warning | 0x01,
+ GODraw = Widget | Drawing | 0x01,
+ GORecreateCache = Widget | Drawing | 0x02,
+ GOUpdateCache = Widget | Drawing | 0x03,
+ GOPaint = Widget | Drawing | 0x04,
GOLockUpdate = Widget | Lock | 0x01,
GOLockClipping = Widget | Lock | 0x02,
TGLoadingThread = Widget | TemplatedGroup | 0x01,
TGCancelLoadingThread = Widget | TemplatedGroup | 0x02,
+ MouseDown = IFace | Mouse | 0x01,
+ MouseUp = IFace | Mouse | 0x02,
+ MouseMove = IFace | Mouse | 0x03,
+ GOMouseDown = Widget | Mouse | 0x01,
+ GOMouseUp = Widget | Mouse | 0x02,
+ GOMouseMove = Widget | Mouse | 0x03,
+
All = 0x7FFFFF00
}
}
\ No newline at end of file
il.Emit (OpCodes.Stfld, miSetCurIface);
}
+ //TODO: should be able to handle struct in default values.
public static void EmitSetValue(ILGenerator il, PropertyInfo pi, object val){
il.Emit (OpCodes.Ldloc_0);
event EventHandler<ListChangedEventArg> ListAdd;
event EventHandler<ListChangedEventArg> ListRemove;
event EventHandler<ListChangedEventArg> ListEdit;
+ event EventHandler<ListChangedEventArg> ListClear;
void Insert ();
void Remove ();
using System.Collections.Generic;
using System.Text;
-namespace Crow.src.Text
+namespace Crow.Text
{
public ref struct SpanCharReader
{
public void Seek (int position) => curPos = position;
- public Char Peak () => buffer[curPos];
+ public Char Peak => buffer[curPos];
public Char Read () => buffer[curPos++];
+ public bool TryRead (out char c) {
+ if (EndOfSpan) {
+ c = default;
+ return false;
+ }
+ c = Read();
+ return true;
+ }
+ public bool TryRead (char c) => EndOfSpan ? false : Read() == c;
+
+ public ReadOnlySpan<char> Read (int length) => buffer.Slice (curPos += length, length);
+ public void Advance (int increment = 1) => curPos += increment;
+ public bool TryAdvance (int increment = 1) {
+ curPos += increment;
+ return curPos < buffer.Length;
+ }
+
+ public bool TryReadUntil (ReadOnlySpan<char> str, StringComparison comparison = StringComparison.Ordinal) {
+ int startPos = curPos;
+ while (curPos < buffer.Length - str.Length) {
+ if (buffer[curPos] == str[0] && buffer.Slice(curPos + 1, str.Length - 1).Equals(str.Slice (1), comparison))
+ return true;
+ curPos++;
+ }
+ return false;
+ }
+ public bool TryReadUntil (char c) {
+ int startPos = curPos;
+ while (curPos < buffer.Length && buffer[curPos] != c)
+ curPos++;
+ return curPos < buffer.Length;
+ }
+ public bool TryRead (int length, out ReadOnlySpan<char> str) {
+ if (length < buffer.Length) {
+ str = buffer.Slice (curPos += length, length);
+ return true;
+ }
+ str = default;
+ return false;
+ }
+
+ /// <summary>
+ /// Try read expected string and advance reader position in any case
+ /// </summary>
+ /// <param name="expectedString">expected string</param>
+ /// <param name="comparison">comparison type</param>
+ /// <returns>true if expected string is found</returns>
+ public bool TryRead (ReadOnlySpan<char> expectedString, StringComparison comparison = StringComparison.OrdinalIgnoreCase) {
+ if (buffer.Length < curPos + expectedString.Length) {
+ curPos = buffer.Length;
+ return false;
+ }
+ bool res = buffer.Slice(curPos, expectedString.Length).Equals (expectedString, comparison);
+ curPos += expectedString.Length;
+ return res;
+ }
+ public bool TryPeak (ReadOnlySpan<char> expectedString, StringComparison comparison = StringComparison.Ordinal) =>
+ (buffer.Length < curPos + expectedString.Length)? false :
+ buffer.Slice(curPos, expectedString.Length).Equals (expectedString, comparison);
+
public ReadOnlySpan<char> Get (int fromPosition) => buffer.Slice (fromPosition, curPos - fromPosition);
public bool EndOfSpan => curPos >= buffer.Length;
+ public bool TryPeak (char c) => !EndOfSpan && Peak == c;
+ public bool TryPeak (ref char c) {
+ if (EndOfSpan)
+ return false;
+ c = buffer[curPos];
+ return true;
+ }
+ public bool IsNextCharIn (params char[] chars) {
+ for (int i = 0; i < chars.Length; i++)
+ if (chars[i] == buffer[curPos])
+ return true;
+ return false;
+ }
}
}
#region GraphicObject overrides
public override void onMouseLeave (object sender, MouseMoveEventArgs e)
{
- base.onMouseLeave (this, e);
IsPopped = false;
+ e.Handled = true;
+ base.onMouseLeave (this, e);
}
public override bool MouseIsIn (Point m)
{
/// <summary> Vertical Scrolling Position </summary>
[DefaultValue(0)]
public virtual int ScrollY {
- get { return scrollY; }
+ get => scrollY;
set {
if (scrollY == value)
return;
/// <summary> Horizontal Scrolling maximum value </summary>
[DefaultValue(0)]
public virtual int MaxScrollX {
- get { return maxScrollX; }
+ get => maxScrollX;
set {
if (maxScrollX == value)
return;
/// <summary> Vertical Scrolling maximum value </summary>
[DefaultValue(0)]
public virtual int MaxScrollY {
- get { return maxScrollY; }
+ get => maxScrollY;
set {
if (maxScrollY == value)
return;
/// <summary> Mouse Wheel Scrolling multiplier </summary>
[DefaultValue(1)]
public virtual int MouseWheelSpeed {
- get { return mouseWheelSpeed; }
+ get => mouseWheelSpeed;
set {
if (mouseWheelSpeed == value)
return;
double tmp = mouseDownInitValue + (double)m.Y * unit;
tmp -= tmp % SmallIncrement;
Value = tmp;
- }
- e.Handled = true;
+ }
}
+ e.Handled = true;
base.onMouseMove (sender, e);
}
/// Keep track of expanded subnodes and closed time to unload
/// </summary>
//Dictionary<GraphicObject, Stopwatch> nodes = new Dictionary<GraphicObject, Stopwatch>();
- internal List<Widget> nodes = new List<Widget>();
+ internal List<Widget> nodes = new List<Widget>();//TODO:close time tracking
/// <summary>
/// Item templates file path, on disk or embedded.
///
ol.ListAdd -= Ol_ListAdd;
ol.ListRemove -= Ol_ListRemove;
ol.ListEdit -= Ol_ListEdit;
+ ol.ListClear -= Ol_ListClear;
+
}
data = value;
ol.ListAdd += Ol_ListAdd;
ol.ListRemove += Ol_ListRemove;
ol.ListEdit += Ol_ListEdit;
+ ol.ListClear += Ol_ListClear;
}
NotifyValueChangedAuto (data);
itemsContainer.Children [e.Index].DataSource = e.Element;
}
+ void Ol_ListClear (object sender, ListChangedEventArg e) {
+ cancelLoadingThread ();
+ if (this.isPaged) {
+ throw new NotImplementedException ();
+ } else {
+ lock (IFace.UpdateMutex)
+ itemsContainer.ClearChildren ();
+ }
+
+ }
protected void raiseSelectedItemChanged(){
void cancelLoadingThread(){
if (loadingThread == null)
return;
- bool updateMx = Monitor.IsEntered (IFace.UpdateMutex);
- bool layoutMx = Monitor.IsEntered (IFace.LayoutMutex);
- DbgLogger.AddEvent (DbgEvtType.TGCancelLoadingThread, this);
+ DbgLogger.StartEvent (DbgEvtType.TGCancelLoadingThread, this);
- if (layoutMx)
- Monitor.Exit (IFace.LayoutMutex);
- if (updateMx)
+ int updateMx = 0, layoutMx = 0;
+
+ while (Monitor.IsEntered (IFace.UpdateMutex)) {
Monitor.Exit (IFace.UpdateMutex);
+ updateMx++;
+ }
+ while (Monitor.IsEntered (IFace.LayoutMutex)) {
+ Monitor.Exit (IFace.LayoutMutex);
+ layoutMx++;
+ }
loadingThread.Cancel ();
- if (layoutMx)
+ for (int i = 0; i < layoutMx; i++)
Monitor.Enter (IFace.LayoutMutex);
- if (updateMx)
+ for (int i = 0; i < updateMx; i++)
Monitor.Enter (IFace.UpdateMutex);
loadingThread = null;
+
+ DbgLogger.EndEvent (DbgEvtType.TGCancelLoadingThread);
}
void loadPage(IEnumerable _data, Group page, string _dataTest)
{
}
catch (System.Exception ex)
{
- if (Monitor.IsEntered(LayoutMutex))
+ while (Monitor.IsEntered(LayoutMutex))
Monitor.Exit (LayoutMutex);
- if (Monitor.IsEntered(UpdateMutex))
+ while (Monitor.IsEntered(UpdateMutex))
Monitor.Exit (UpdateMutex);
- if (Monitor.IsEntered(ClippingMutex))
+ while (Monitor.IsEntered(ClippingMutex))
Monitor.Exit (ClippingMutex);
delSetCurrentException (ex);
ClearInterface();
public override void onMouseMove(object sender, MouseMoveEventArgs e)
{
- if (initialized) {
- Point m = ScreenPointToLocal (e.Position);
- delMouseMove (m.X, m.Y);
+ if (initialized) {
+ try
+ {
+ Point m = ScreenPointToLocal (e.Position);
+ delMouseMove (m.X, m.Y);
+ }
+ catch (System.Exception ex)
+ {
+ Console.WriteLine($"[Error][DebugIFace mouse move]{ex}");
+ }
e.Handled = true;
}
base.onMouseMove(sender, e);
public override void onMouseDown(object sender, MouseButtonEventArgs e)
{
if (initialized) {
- delMouseDown (e.Button);
+ try
+ {
+ delMouseDown (e.Button);
+ }
+ catch (System.Exception ex)
+ {
+ Console.WriteLine($"[Error][DebugIFace mouse down]{ex}");
+ }
e.Handled=true;
}
base.onMouseDown (sender, e);
public override void onMouseUp(object sender, MouseButtonEventArgs e)
{
if (initialized) {
- delMouseUp (e.Button);
+ try
+ {
+ delMouseUp (e.Button);
+ }
+ catch (System.Exception ex)
+ {
+ Console.WriteLine($"[Error][DebugIFace mouse up]{ex}");
+ }
e.Handled=true;
}
base.onMouseUp (sender, e);
+++ /dev/null
-// Copyright (c) 2013-2019 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-using Glfw;
-using Crow.Text;
-
-namespace Crow
-{
- public class Editor : TextBox {
- public override void onKeyDown(object sender, KeyEventArgs e)
- {
- TextSpan selection = Selection;
- if (e.Key == Key.Tab && !selection.IsEmpty) {
- int lineStart = lines.GetLocation (selection.Start).Line;
- int lineEnd = lines.GetLocation (selection.End).Line;
-
- if (IFace.Shift) {
- for (int l = lineStart; l <= lineEnd; l++) {
- if (Text[lines[l].Start] == '\t')
- update (new TextChange (lines[l].Start, 1, ""));
- else if (Char.IsWhiteSpace (Text[lines[l].Start])) {
- int i = 1;
- while (i < lines[l].Length && i < Interface.TAB_SIZE && Char.IsWhiteSpace (Text[i]))
- i++;
- update (new TextChange (lines[l].Start, i, ""));
- }
- }
-
- }else{
- for (int l = lineStart; l <= lineEnd; l++)
- update (new TextChange (lines[l].Start, 0, "\t"));
- }
-
- selectionStart = new CharLocation (lineStart, 0);
- CurrentLoc = new CharLocation (lineEnd, lines[lineEnd].Length);
-
- return;
- }
- base.onKeyDown(sender, e);
- }
- }
-}
\ No newline at end of file
<EmbeddedResource Include="$(SamplesDir)common\samples.style" >
<Link>common\%(Filename)%(Extension)</Link>
</EmbeddedResource>
- <Compile Include="$(SamplesDir)common\SampleBase.cs">
+ <Compile Include="$(SamplesDir)common\*.cs">
<Link>common\%(Filename)%(Extension)</Link>
</Compile>
</ItemGroup>
+++ /dev/null
-// Copyright (c) 2013-2019 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-using Glfw;
-using Crow.Text;
-
-namespace Crow
-{
- public class Editor : TextBox {
- public override void onKeyDown(object sender, KeyEventArgs e)
- {
- TextSpan selection = Selection;
- if (e.Key == Key.Tab && !selection.IsEmpty) {
- int lineStart = lines.GetLocation (selection.Start).Line;
- int lineEnd = lines.GetLocation (selection.End).Line;
-
- if (IFace.Shift) {
- for (int l = lineStart; l <= lineEnd; l++) {
- if (Text[lines[l].Start] == '\t')
- update (new TextChange (lines[l].Start, 1, ""));
- else if (Char.IsWhiteSpace (Text[lines[l].Start])) {
- int i = 1;
- while (i < lines[l].Length && i < Interface.TAB_SIZE && Char.IsWhiteSpace (Text[i]))
- i++;
- update (new TextChange (lines[l].Start, i, ""));
- }
- }
-
- }else{
- for (int l = lineStart; l <= lineEnd; l++)
- update (new TextChange (lines[l].Start, 0, "\t"));
- }
-
- selectionStart = new CharLocation (lineStart, 0);
- CurrentLoc = new CharLocation (lineEnd, lines[lineEnd].Length);
-
- return;
- }
- base.onKeyDown(sender, e);
- }
- }
-}
\ No newline at end of file
<HorizontalStack>
<Editor Name="tb" Text="{Source}" Multiline="true" Font="consolas, 12" Focusable="true" Height="Stretched" Width="Stretched"
TextChanged="onTextChanged" KeyDown="textView_KeyDown" ContextCommands="{EditorCommands}"
- Foreground="DarkGrey" Background="White"/>
+ Foreground="DarkGrey" Background="White" MouseWheelSpeed="20"/>
<!--SelectionChanged="onSelectedTextChanged"-->
<ScrollBar Value="{²../tb.ScrollY}"
LargeIncrement="{../tb.PageHeight}" SmallIncrement="1"
--- /dev/null
+using System.Security.Principal;
+using System.Threading;
+// Copyright (c) 2013-2019 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using Glfw;
+using Crow.Text;
+using System.Collections.Generic;
+using Crow.Cairo;
+using System.Threading.Tasks;
+using System.Linq;
+
+namespace Crow
+{
+ [Flags]
+ public enum TokenType {
+ Unknown,
+ Trivia = 0x0100,
+ WhiteSpace = 0x4100,
+ Tabulation = 0x4101,
+ LineBreak = 0x4102,
+ LineComment = 0x0103,
+ BlockCommentStart = 0x0104,
+ BlockComment = 0x0105,
+ BlockCommentEnd = 0x0106,
+ Name = 0x0200,
+ ElementName = 0x0201,
+ AttributeName = 0x0202,
+ PI_Target = 0x0203,
+ Punctuation = 0x0400,
+ PI_Start = 0x0401,// '<?'
+ PI_End = 0x0402,// '?>'
+ Operator = 0x0800,
+ EqualSign = 0x0801,
+ AttributeValue = 0x2000,
+ Keyword = 0x1000,
+ ElementOpen = 0x0403,// '<'
+ EndElementOpen = 0x0404,// '</'
+ EmptyElementClosing = 0x0405,// '/>'
+ ClosingSign = 0x0406,// '>'
+ DTDObjectOpen = 0x04A0,// '<!'
+ Content,
+ }
+
+ public struct Token {
+ public readonly TokenType Type;
+ public int Start;
+ public readonly int Length;
+ public int End => Start + Length;
+ public TextSpan Span => new TextSpan (Start, End);
+
+ public Token (TokenType type, int pos) {
+ Type = type;
+ Start = pos;
+ Length = 1;
+ }
+ public Token (TokenType type, int start, int end) {
+ Type = type;
+ Start = start;
+ Length = end - start;
+ }
+ public override string ToString() => $"{Type},{Start} {Length}";
+ }
+ public class XmlSource {
+ public Token[] Tokens;
+ public readonly string Source;
+
+ public XmlSource (string _source) {
+ Source = _source;
+ Tokenizer tokenizer = new Tokenizer();
+ Tokens = tokenizer.Tokenize (Source);
+
+ foreach (Token t in Tokens)
+ Console.WriteLine ($"{t,-40} {Source.AsSpan(t.Start, t.Length).ToString()}");
+ }
+ public class TokenizerException : Exception {
+ public readonly int Position;
+ public TokenizerException(string message, int position, Exception innerException = null)
+ : base (message, innerException) {
+ Position = position;
+ }
+ }
+
+ class Tokenizer {
+ enum States
+ {
+ Init,//first statement of prolog, xmldecl should only apear in this state
+ prolog,//misc before doctypedecl
+ ProcessingInstrucitons,
+ DTD,
+ DTDObject,//doctype finished
+ Xml,
+ StartTag,//inside start tag
+ Content,//after start tag with no closing slash
+ EndTag
+ }
+
+ States curState = States.Init;
+ List<Token> Toks = new List<Token>(100);
+
+ public Tokenizer () {}
+
+ void skipWhiteSpaces (ref SpanCharReader reader) {
+ while(!reader.EndOfSpan) {
+ switch (reader.Peak) {
+ case '\x85':
+ case '\x2028':
+ case '\xA':
+ reader.Read();
+ addTok (ref reader, TokenType.LineBreak);
+ break;
+ case '\xD':
+ reader.Read();
+ if (reader.IsNextCharIn ('\xA', '\x85'))
+ reader.Read();
+ addTok (ref reader, TokenType.LineBreak);
+ break;
+ case '\x20':
+ case '\x9':
+ char c = reader.Read();
+ while (reader.TryPeak (c))
+ reader.Read();
+ addTok (ref reader, c == '\x20' ? TokenType.WhiteSpace : TokenType.Tabulation);
+ break;
+ default:
+ return;
+ }
+ }
+ }
+ bool readName (ref SpanCharReader reader) {
+ if (reader.EndOfSpan)
+ return false;
+ char c = reader.Peak;
+ if (char.IsLetter(c) || c == '_' || c == ':') {
+ reader.Advance ();
+ while (reader.TryPeak (ref c)) {
+ if (!(char.IsLetterOrDigit(c) || c == '.' || c == '-' || c == '\xB7'))
+ return true;
+ reader.Advance ();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ int startOfTok;
+ void addTok (ref SpanCharReader reader, TokenType tokType) {
+ if (reader.CurrentPosition == startOfTok)
+ return;
+ Toks.Add (new Token(tokType, startOfTok, reader.CurrentPosition));
+ startOfTok = reader.CurrentPosition;
+ }
+ public Token[] Tokenize (string source) {
+ SpanCharReader reader = new SpanCharReader(source);
+
+ startOfTok = 0;
+ int curObjectLevel = 0;
+ curState = States.Init;
+
+ while(!reader.EndOfSpan) {
+
+ skipWhiteSpaces (ref reader);
+
+ if (reader.EndOfSpan)
+ break;
+
+ switch (reader.Peak) {
+ case '<':
+ reader.Advance ();
+ if (reader.TryPeak ('?')) {
+ reader.Advance ();
+ addTok (ref reader, TokenType.PI_Start);
+ readName (ref reader);
+ addTok (ref reader, TokenType.PI_Target);
+ curState = States.ProcessingInstrucitons;
+ } else if (reader.TryPeak ('!')) {
+ reader.Advance ();
+ if (reader.TryPeak ("--")) {
+ reader.Advance (2);
+ addTok (ref reader, TokenType.BlockCommentStart);
+ if (reader.TryReadUntil ("-->")) {
+ addTok (ref reader, TokenType.BlockComment);
+ reader.Advance (3);
+ addTok (ref reader, TokenType.BlockCommentEnd);
+ } else if (reader.TryPeak ("-->")) {
+ reader.Advance (3);
+ addTok (ref reader, TokenType.BlockCommentEnd);
+ }
+ } else {
+ addTok (ref reader, TokenType.DTDObjectOpen);
+ if (readName (ref reader)) {
+ addTok (ref reader, TokenType.Keyword);
+ curState = States.DTDObject;
+ }
+ }
+ } else if (reader.TryPeak('/')) {
+ reader.Advance ();
+ addTok (ref reader, TokenType.EndElementOpen);
+ if (readName (ref reader)) {
+ addTok (ref reader, TokenType.ElementName);
+ if (reader.TryPeak('>')) {
+ reader.Advance ();
+ addTok (ref reader, TokenType.ClosingSign);
+
+ if (--curObjectLevel > 0)
+ curState = States.Content;
+ else
+ curState = States.Xml;
+ }
+ }
+ }else{
+ addTok (ref reader, TokenType.ElementOpen);
+ if (readName (ref reader)) {
+ addTok (ref reader, TokenType.ElementName);
+ curState = States.StartTag;
+ }
+ }
+ break;
+ case '?':
+ reader.Advance ();
+ if (reader.TryPeak ('>')){
+ reader.Advance ();
+ addTok (ref reader, TokenType.PI_End);
+ }else
+ addTok (ref reader, TokenType.Unknown);
+ curState = States.prolog;
+ break;
+ case '\'':
+ case '"':
+ char q = reader.Read();
+ if (reader.TryReadUntil (q)) {
+ reader.Advance ();
+ addTok (ref reader, TokenType.AttributeValue);
+ } else
+ addTok (ref reader, TokenType.Unknown);
+ break;
+ case '=':
+ reader.Advance();
+ addTok (ref reader, TokenType.EqualSign);
+ break;
+ case '>':
+ reader.Advance();
+ addTok (ref reader, TokenType.ClosingSign);
+ curObjectLevel++;
+ curState = States.Content;
+ break;
+ case '/':
+ reader.Advance();
+ if (reader.TryRead ('>')) {
+ addTok (ref reader, TokenType.EmptyElementClosing);
+ if (--curObjectLevel > 0)
+ curState = States.Content;
+ else
+ curState = States.Xml;
+ }else
+ addTok (ref reader, TokenType.Unknown);
+ break;
+ default:
+ if (curState == States.StartTag || curState == States.ProcessingInstrucitons) {
+ if (readName(ref reader))
+ addTok (ref reader, TokenType.AttributeName);
+ else if (reader.TryAdvance())
+ addTok (ref reader, TokenType.Unknown);
+ } else {
+ reader.TryReadUntil ('<');
+ addTok (ref reader, TokenType.Content);
+ }
+ break;
+ }
+ }
+
+ return Toks.ToArray();
+ }
+
+ }
+
+ }
+ public class Editor : TextBox {
+ XmlSource source;
+ object TokenMutex = new object();
+
+ void parse () {
+ XmlSource tmp = new XmlSource(_text);
+ lock(TokenMutex)
+ source = tmp;
+ RegisterForGraphicUpdate();
+ }
+ protected override void onInitialized(object sender, EventArgs e)
+ {
+ base.onInitialized(sender, e);
+
+ }
+ Widget overlay;
+ public override void OnTextChanged(object sender, TextChangeEventArgs e)
+ {
+ base.OnTextChanged(sender, e);
+ //Task.Run(()=>parse());
+ parse();
+
+ /*if (overlay == null && HasFocus)
+ overlay = IFace.LoadIMLFragment(@"<Widget Width='50' Height='50' Background='Jet'/>");*/
+ }
+ public override void onKeyDown(object sender, KeyEventArgs e)
+ {
+ TextSpan selection = Selection;
+ if (e.Key == Key.Tab && !selection.IsEmpty) {
+ int lineStart = lines.GetLocation (selection.Start).Line;
+ int lineEnd = lines.GetLocation (selection.End).Line;
+
+ if (IFace.Shift) {
+ for (int l = lineStart; l <= lineEnd; l++) {
+ if (Text[lines[l].Start] == '\t')
+ update (new TextChange (lines[l].Start, 1, ""));
+ else if (Char.IsWhiteSpace (Text[lines[l].Start])) {
+ int i = 1;
+ while (i < lines[l].Length && i < Interface.TAB_SIZE && Char.IsWhiteSpace (Text[i]))
+ i++;
+ update (new TextChange (lines[l].Start, i, ""));
+ }
+ }
+
+ }else{
+ for (int l = lineStart; l <= lineEnd; l++)
+ update (new TextChange (lines[l].Start, 0, "\t"));
+ }
+
+ selectionStart = new CharLocation (lineStart, 0);
+ CurrentLoc = new CharLocation (lineEnd, lines[lineEnd].Length);
+
+ return;
+ }
+ base.onKeyDown(sender, e);
+ }
+ int tabSize = 4;
+
+ protected override void drawContent (Context gr) {
+ lock(TokenMutex) {
+ if (source == null || source.Tokens.Length == 0) {
+ base.drawContent (gr);
+ return;
+ }
+
+ Rectangle cb = ClientRectangle;
+ fe = gr.FontExtents;
+ double lineHeight = fe.Ascent + fe.Descent;
+
+ CharLocation selStart = default, selEnd = default;
+ bool selectionNotEmpty = false;
+
+ if (HasFocus) {
+ if (currentLoc?.Column < 0) {
+ updateLocation (gr, cb.Width, ref currentLoc);
+ NotifyValueChanged ("CurrentColumn", CurrentColumn);
+ } else
+ updateLocation (gr, cb.Width, ref currentLoc);
+
+ if (overlay != null) {
+ Point p = new Point((int)currentLoc.Value.VisualCharXPosition, (int)(lineHeight * (currentLoc.Value.Line + 1)));
+ p += ScreenCoordinates (Slot).TopLeft;
+ overlay.Left = p.X;
+ overlay.Top = p.Y;
+ }
+ if (selectionStart.HasValue) {
+ updateLocation (gr, cb.Width, ref selectionStart);
+ if (CurrentLoc.Value != selectionStart.Value)
+ selectionNotEmpty = true;
+ }
+ if (selectionNotEmpty) {
+ if (CurrentLoc.Value.Line < selectionStart.Value.Line) {
+ selStart = CurrentLoc.Value;
+ selEnd = selectionStart.Value;
+ } else if (CurrentLoc.Value.Line > selectionStart.Value.Line) {
+ selStart = selectionStart.Value;
+ selEnd = CurrentLoc.Value;
+ } else if (CurrentLoc.Value.Column < selectionStart.Value.Column) {
+ selStart = CurrentLoc.Value;
+ selEnd = selectionStart.Value;
+ } else {
+ selStart = selectionStart.Value;
+ selEnd = CurrentLoc.Value;
+ }
+ } else
+ IFace.forceTextCursor = true;
+ }
+
+ double spacePixelWidth = gr.TextExtents (" ").XAdvance;
+ int x = 0, y = 0;
+ double pixX = cb.Left;
+
+
+ Foreground.SetAsSource (IFace, gr);
+ gr.Translate (-ScrollX, -ScrollY);
+
+
+ ReadOnlySpan<char> sourceBytes = source.Source.AsSpan();
+ Span<byte> bytes = stackalloc byte[128];
+ TextExtents extents;
+ int tokPtr = 0;
+ Token tok = source.Tokens[tokPtr];
+ bool multilineToken = false;
+
+ ReadOnlySpan<char> buff = sourceBytes;
+
+
+ for (int i = 0; i < lines.Count; i++) {
+ //if (!cancelLinePrint (lineHeight, lineHeight * y, cb.Height)) {
+
+ if (multilineToken) {
+ if (tok.End < lines[i].End) {//last incomplete line of multiline token
+ buff = sourceBytes.Slice (lines[i].Start, tok.End - lines[i].Start);
+ } else {//print full line
+ buff = sourceBytes.Slice (lines[i].Start, lines[i].Length);
+ }
+ }
+
+ while (tok.Start < lines[i].End) {
+ if (!multilineToken) {
+ if (tok.End > lines[i].End) {//first line of multiline
+ multilineToken = true;
+ buff = sourceBytes.Slice (tok.Start, lines[i].End - tok.Start);
+ } else
+ buff = sourceBytes.Slice (tok.Start, tok.Length);
+
+ if (tok.Type.HasFlag (TokenType.Punctuation))
+ gr.SetSource(Colors.DarkGrey);
+ else if (tok.Type.HasFlag (TokenType.Trivia))
+ gr.SetSource(Colors.DimGrey);
+ else if (tok.Type == TokenType.ElementName) {
+ gr.SetSource(Colors.Green);
+ }else if (tok.Type == TokenType.AttributeName) {
+ gr.SetSource(Colors.Blue);
+ }else if (tok.Type == TokenType.AttributeValue) {
+ gr.SetSource(Colors.OrangeRed);
+ }else if (tok.Type == TokenType.EqualSign) {
+ gr.SetSource(Colors.Black);
+ }else if (tok.Type == TokenType.PI_Target) {
+ gr.SetSource(Colors.DarkSlateBlue);
+ }else {
+ gr.SetSource(Colors.Red);
+ }
+ }
+
+ int size = buff.Length * 4 + 1;
+ if (bytes.Length < size)
+ bytes = size > 512 ? new byte[size] : stackalloc byte[size];
+
+ int encodedBytes = Crow.Text.Encoding.ToUtf8 (buff, bytes);
+
+ if (encodedBytes > 0) {
+ bytes[encodedBytes++] = 0;
+ gr.TextExtents (bytes.Slice (0, encodedBytes), out extents);
+ gr.MoveTo (pixX, lineHeight * y + fe.Ascent);
+ gr.ShowText (bytes.Slice (0, encodedBytes));
+ pixX += extents.XAdvance;
+ x += buff.Length;
+ }
+
+ if (multilineToken) {
+ if (tok.End < lines[i].End)//last incomplete line of multiline token
+ multilineToken = false;
+ else
+ break;
+ }
+
+ if (++tokPtr >= source.Tokens.Length)
+ break;
+ tok = source.Tokens[tokPtr];
+ }
+
+ if (HasFocus && selectionNotEmpty) {
+ RectangleD lineRect = new RectangleD (cb.X, lineHeight * y + cb.Top, pixX, lineHeight);
+ RectangleD selRect = lineRect;
+
+ if (i >= selStart.Line && i <= selEnd.Line) {
+ if (selStart.Line == selEnd.Line) {
+ selRect.X = selStart.VisualCharXPosition + cb.X;
+ selRect.Width = selEnd.VisualCharXPosition - selStart.VisualCharXPosition;
+ } else if (i == selStart.Line) {
+ double newX = selStart.VisualCharXPosition + cb.X;
+ selRect.Width -= (newX - selRect.X) - 10.0;
+ selRect.X = newX;
+ } else if (i == selEnd.Line)
+ selRect.Width = selEnd.VisualCharXPosition - selRect.X + cb.X;
+ else
+ selRect.Width += 10.0;
+
+ buff = sourceBytes.Slice(lines[i].Start, lines[i].Length);
+ int size = buff.Length * 4 + 1;
+ if (bytes.Length < size)
+ bytes = size > 512 ? new byte[size] : stackalloc byte[size];
+
+ int encodedBytes = Crow.Text.Encoding.ToUtf8 (buff, bytes);
+
+ gr.SetSource (SelectionBackground);
+ gr.Rectangle (selRect);
+ if (encodedBytes < 0)
+ gr.Fill ();
+ else {
+ gr.FillPreserve ();
+ gr.Save ();
+ gr.Clip ();
+ gr.SetSource (SelectionForeground);
+ gr.MoveTo (lineRect.X, lineRect.Y + fe.Ascent);
+ gr.ShowText (bytes.Slice (0, encodedBytes));
+ gr.Restore ();
+ }
+ Foreground.SetAsSource (IFace, gr);
+ }
+ }
+
+ if (!multilineToken) {
+ if (++tokPtr >= source.Tokens.Length)
+ break;
+ tok = source.Tokens[tokPtr];
+ }
+
+ x = 0;
+ pixX = 0;
+
+ y++;
+
+
+ /* } else if (tok2.Type == TokenType.Tabulation) {
+ int spaceRounding = x % tabSize;
+ int spaces = spaceRounding == 0 ?
+ tabSize * tok2.Length :
+ spaceRounding + tabSize * (tok2.Length - 1);
+ x += spaces;
+ pixX += spacePixelWidth * spaces;
+ continue;
+ } else if (tok2.Type == TokenType.WhiteSpace) {
+ x += tok2.Length;
+ pixX += spacePixelWidth * tok2.Length;*/
+ }
+ gr.Translate (ScrollX, ScrollY);
+ }
+ }
+ }
+}
\ No newline at end of file
public override string ToString ()
=> $"{Prop1}, {Prop2}";
+ public void OnValidateCommand (Object sender, ValidateEventArgs e) {
+ Console.WriteLine ($"Validation: {e.ValidatedText}");
+ }
}
public class TestClassVC : IValueChange
{
=> $"{Prop1}, {Prop2}";
}
- TestClass tcInstance;// = new TestClass () { Prop1 = "instance 0 prop1 value", Prop2 = "instance 0 prop2 value" };
+ TestClass tcInstance = new TestClass () { Prop1 = "instance 0 prop1 value", Prop2 = "instance 0 prop2 value" };
TestClassVC tcVCInstance;// = new TestClassVC () { Prop1 = "instance 0 prop1 value", Prop2 = "instance 0 prop2 value" };
TestClass tcInstance1 = new TestClass () { Prop1 = "instance 1 prop1 value", Prop2 = "instance 1 prop2 value" };
TestClassVC tcVCInstance1 = new TestClassVC () { Prop1 = "instance 1 prop1 value", Prop2 = "instance 1 prop2 value" };
<VerticalStack>
- <ColorPicker Name="cp" Height="20" Background="Grey" >
+ <ColorPicker Name="cp" >
<Template>
<Popper Margin="0" Caption="{./CurrentColor}" Background="{./Background}" >
<Template>
</Template>/>{}
</CheckBox>
</Template>
- <TabView TabWidth="60" LeftSlope="0" RightSlope="0" MinimumSize="{../../MinimumPopupSize}" Width="Fit" Height="Fit" ActivateNewTab="false">
- <TabItem Template="/mnt/devel/crow/Samples/common/ui/templates/TabItem.template" Caption="HSV" Width="Fit" Height="Fit">
- <ColorPicker CurrentColor="{²../../../../CurrentColor}" />
- </TabItem>
- <TabItem Template="/mnt/devel/crow/Samples/common/ui/templates/TabItem.template" Caption="Names" Width="Fit" Height="Stretched">
- <ColorPicker CurrentColor="{²../../../../CurrentColor}" Height="Stretched" >
- <Template>
- <ListBox Margin="0" Width="Stretched" Data="{./AvailableColors}" SelectedItemChanged="./onSelectedItemChanged">
- <Template>
- <Scroller Name="scroller1" Margin="5" ClipToClientRect="true" >
- <Wrapper Name="ItemsContainer" Height="Fit" VerticalAlignment="Top"/>
- </Scroller>
- </Template>
- <ItemTemplate>
- <Border Width="16" Height="16" Background="{}" Foreground="Transparent" Tooltip="{}"
- MouseEnter="{Foreground=Black}"
- MouseLeave="{Foreground=Transparent}"/>
- </ItemTemplate>
- </ListBox>
- </Template>
- </ColorPicker>
- </TabItem>
- </TabView>
+ <TabView MinimumSize="{../../MinimumPopupSize}" Width="Fit" Height="Fit" >
+ <ColorPicker Name="HSV" CurrentColor="{²../../../CurrentColor}" Background="Onyx"/>
+ <ColorPicker IsVisible="false" Name="Names" CurrentColor="{²../../../CurrentColor}" Height="Stretched" Background="Onyx">
+ <Template>
+ <ListBox Width="Stretched" Data="{./AvailableColors}" SelectedItemChanged="./onSelectedItemChanged">
+ <Template>
+ <Scroller Name="scroller1" Margin="5" ClipToClientRect="true" Background="Onyx">
+ <Wrapper Name="ItemsContainer" Height="Fit" VerticalAlignment="Top"/>
+ </Scroller>
+ </Template>
+ <ItemTemplate>
+ <Border Width="16" Height="16" Background="{}" Foreground="Transparent" Tooltip="{}"
+ MouseEnter="{Foreground=Black}"
+ MouseLeave="{Foreground=Transparent}"/>
+ </ItemTemplate>
+ </ListBox>
+ </Template>
+ </ColorPicker>
+ </TabView>
</Popper>
</Template>
</ColorPicker>
- <Border CornerRadius="5" Width="60" Height="40" Background="{../cp.CurrentColor}">
+ <Border CornerRadius="5" Width="100" Height="80" Background="{../cp.CurrentColor}">
<Label Text="{../../cp.CurrentColor}"/>
</Border>
</VerticalStack>
\ No newline at end of file
<?xml version="1.0"?>
-<TabView >
- <TabItem Caption="HSV">
- <Border Background="{./Background}" Foreground="{./Foreground}" Width="Stretched"
- CornerRadius="{./CornerRadius}" BorderWidth="1">
- <VerticalStack Margin="2">
- <Widget Width="30" Height="16" Background="{./CurrentColor}"/>
- <HorizontalStack Height="Fit">
- <Label Style="labColor" Text="R:"/>
- <ColorSlider Name="cs" Component="Red" CurrentColor="{²../../../../../../CurrentColor}"/>
- <Label Style="labColorV" Text="{../cs.CurrentValue}" />
- </HorizontalStack>
- <HorizontalStack Height="Fit">
- <Label Style="labColor" Text="G:"/>
- <ColorSlider Name="cs" Component="Green" CurrentColor="{²../../../../../../CurrentColor}"/>
- <Label Style="labColorV" Text="{../cs.CurrentValue}" />
- </HorizontalStack>
- <HorizontalStack Height="Fit">
- <Label Style="labColor" Text="B:"/>
- <ColorSlider Name="cs" Component="Blue" CurrentColor="{²../../../../../../CurrentColor}"/>
- <Label Style="labColorV" Text="{../cs.CurrentValue}" />
- </HorizontalStack>
- <HorizontalStack Height="Fit">
- <Label Style="labColor" Text="A:"/>
- <ColorSlider Name="cs" Component="Alpha" CurrentColor="{²../../../../../../CurrentColor}"/>
- <Label Style="labColorV" Text="{../cs.CurrentValue}" />
- </HorizontalStack>
- <HorizontalStack Height="Fit">
- <Label Style="labColor" Text="H:"/>
- <ColorSlider Name="cs" Component="Hue" CurrentColor="{²../../../../../../CurrentColor}"/>
- <Label Style="labColorV" Text="{../cs.CurrentValue}" />
- </HorizontalStack>
- <HorizontalStack Height="Fit">
- <Label Style="labColor" Text="S:"/>
- <ColorSlider Name="cs" Component="Saturation" CurrentColor="{²../../../../../../CurrentColor}"/>
- <Label Style="labColorV" Text="{../cs.CurrentValue}" />
- </HorizontalStack>
- <HorizontalStack Height="Fit">
- <Label Style="labColor" Text="V:"/>
- <ColorSlider Name="cs" Component="Value" CurrentColor="{²../../../../../../CurrentColor}"/>
- <Label Style="labColorV" Text="{../cs.CurrentValue}" />
- </HorizontalStack>
- </VerticalStack>
- </Border>
- </TabItem>
- <TabItem Caption="List" Height="Stretched">
- <ListBox Data="{../../../ColorList}" SelectedItem="{²../../../CurrentColor}">
- <Template>
- <Scroller Name="scroller1" Margin="5">
- <Wrapper Name="ItemsContainer" Height="Fit" VerticalAlignment="Top"/>
- </Scroller>
- </Template>
- <ItemTemplate>
- <Border Width="16" Height="16" Background="{}" Foreground="Transparent" Tooltip="{}"
- MouseEnter="{Foreground=Black}"
- MouseLeave="{Foreground=Transparent}"/>
- </ItemTemplate>
- </ListBox>
- </TabItem>
-</TabView>
\ No newline at end of file
+<Popper Margin="0" Caption="{./CurrentColor}" Background="{./Background}" >
+ <Template>
+ <CheckBox Margin="0" Caption="{./Caption}" IsChecked="{²./IsPopped}" Background="{./Background}">
+ <Template>
+ <HorizontalStack Margin="3" Spacing="3" Background="{./Background}">
+ <Border Width="18" Height="12" CornerRadius="3"
+ Background="{../../../../CurrentColor}">
+ </Border>
+ <Label Width="Stretched" Text="{./Caption}" />
+ </HorizontalStack>
+ </Template>/>{}
+ </CheckBox>
+ </Template>
+ <TabView MinimumSize="{../../MinimumPopupSize}" Width="Fit" Height="Fit" >
+ <ColorPicker Name="HSV" CurrentColor="{²../../../CurrentColor}" Background="Onyx"/>
+ <ColorPicker IsVisible="false" Name="Names" CurrentColor="{²../../../CurrentColor}" Height="Stretched" Background="Onyx">
+ <Template>
+ <ListBox Width="Stretched" Data="{./AvailableColors}" SelectedItemChanged="./onSelectedItemChanged">
+ <Template>
+ <Scroller Name="scroller1" Margin="5" ClipToClientRect="true" Background="Onyx">
+ <Wrapper Name="ItemsContainer" Height="Fit" VerticalAlignment="Top"/>
+ </Scroller>
+ </Template>
+ <ItemTemplate>
+ <Border Width="16" Height="16" Background="{}" Foreground="Transparent" Tooltip="{}"
+ MouseEnter="{Foreground=Black}"
+ MouseLeave="{Foreground=Transparent}"/>
+ </ItemTemplate>
+ </ListBox>
+ </Template>
+ </ColorPicker>
+ </TabView>
+ </Popper>
\ No newline at end of file