public SourceDocument (string fullPath, string editorPath = "#ui.sourceEditor.itmp")
: base (fullPath, editorPath) {
}
- protected Token[] tokens;
protected SyntaxRootNode root;
- protected int currentTokenIndex;
- SyntaxNode currentNode;
-
- protected Token currentToken => currentTokenIndex < 0 ? default : tokens[currentTokenIndex];
- protected Token? previousToken {
- get {
- if (currentTokenIndex < 1)
- return null;
- return tokens[currentTokenIndex-1];
- }
- }
- public SyntaxNode CurrentNode {
- get => currentNode;
- set {
- if (currentNode == value)
- return;
- currentNode = value;
- NotifyValueChanged ("CurrentNode", currentNode);
- }
- }
- public string CurrentTokenString => root?.GetTokenStringByIndex (currentTokenIndex);
- public Token CurrentToken => currentToken;
- public bool IsParsed => tokens.Length > 0 && root != null;
public SyntaxRootNode Root => root;
+ public bool IsParsed => root != null && Tokens.Length > 0;
//public SyntaxNode EditedNode { get; protected set; }
- public Token[] Tokens => tokens;
+ public ReadOnlySpan<Token> Tokens => root.Tokens;
public IEnumerable<SyntaxNode> SyntaxRootChildNodes => root?.children;
public Token FindTokenIncludingPosition (int pos) {
- if (pos == 0 || tokens == null || tokens.Length == 0)
+ if (!IsParsed || pos == 0 || Tokens.Length == 0)
return default;
- int idx = Array.BinarySearch (tokens, 0, tokens.Length, new Token () {Start = pos});
-
- return idx == 0 ? tokens[0] : idx < 0 ? tokens[~idx - 1] : tokens[idx];
+ int idx = Tokens.BinarySearch(new Token () {Start = pos});
+ return idx == 0 ? Tokens[0] : idx < 0 ? Tokens[~idx - 1] : Tokens[idx];
}
+ public Token GetTokenByIndex(int tokIdx) => IsParsed && tokIdx >= 0 ?
+ Tokens[Math.Min(Tokens.Length - 1, tokIdx)] : default;
public int FindTokenIndexIncludingPosition (int pos) {
- if (pos == 0 || tokens == null || tokens.Length == 0)
+ if (!IsParsed || pos == 0 || Tokens.Length == 0)
return default;
- int idx = Array.BinarySearch (tokens, 0, tokens.Length, new Token () {Start = pos});
-
+ int idx = Tokens.BinarySearch(new Token () {Start = pos});
return idx == 0 ? 0 : idx < 0 ? ~idx - 1 : idx - 1;
}
+
+
/// <summary>
/// if outermost is true, return oldest ancestor exept root node, useful for folding.
/// </summary>
base.apply(change);
- Tokenizer tokenizer = CreateTokenizer ();
SyntaxAnalyser syntaxAnalyser = CreateSyntaxAnalyser ();
-
- if (syntaxAnalyser == null) {
- root = null;
- return;
- }
+ root = syntaxAnalyser?.Process ();
+
+ NotifyValueChanged("Exceptions", syntaxAnalyser?.Exceptions);
//SyntaxNode changedNode = root.FindNodeIncludingSpan (TextSpan.FromStartAndLength (change.Start, change.ChangedText.Length));
- tokens = tokenizer.Tokenize (buffer.Span);
- syntaxAnalyser.Process ();
-
- root = syntaxAnalyser.Root;
- NotifyValueChanged("Exceptions", syntaxAnalyser.Exceptions);
+
/*
SyntaxNode newNode = syntaxAnalyser.Root.FindNodeIncludingSpan (TextSpan.FromStartAndLength (change.Start, change.ChangedText.Length));
//Console.WriteLine ($"CurrentToken: idx({currentTokenIndex}) {currentToken} {RootNode.Root.GetTokenStringByIndex(currentTokenIndex)}");
}
- static bool tryReplaceNode (SyntaxNode editedNode, SyntaxNode newNode) {
+ /*static bool tryReplaceNode (SyntaxNode editedNode, SyntaxNode newNode) {
if (newNode is SyntaxRootNode || editedNode is SyntaxRootNode)
return false;
editedNode.Replace (newNode);
return true;
}
- internal void updateCurrentTokAndNode (CharLocation loc) {
- int pos = buffer.GetAbsolutePosition(loc);
- if (tokens.Length > 0) {
- currentTokenIndex = FindTokenIndexIncludingPosition (pos);
- CurrentNode = root?.FindNodeIncludingSpan (currentToken.Span);
- NotifyValueChanged ("CurrentTokenString", (object)CurrentTokenString);
- //NotifyValueChanged ("CurrentTokenType", (uint)(currentToken.Type)>>8);
- NotifyValueChanged ("CurrentTokenType", (object)GetTokenTypeString(currentToken.Type));
- }else {
- currentTokenIndex = -1;
- CurrentNode = null;
- NotifyValueChanged ("CurrentTokenString", (object)"no token");
- }
- }
+ */
public virtual Color GetColorForToken (TokenType tokType) {
if (tokType.HasFlag (TokenType.Punctuation))
return Colors.Red;
}
public virtual string GetTokenTypeString (TokenType tokenType) => tokenType.ToString();
- protected abstract Tokenizer CreateTokenizer ();
+ //protected abstract Tokenizer CreateTokenizer ();
protected abstract SyntaxAnalyser CreateSyntaxAnalyser ();
- public abstract IList GetSuggestions (CharLocation loc);
+ public abstract IList GetSuggestions (Token currentToken, SyntaxNode currentNode, CharLocation loc);
/// <summary>
/// complete current token with selected item from the suggestion overlay.
/// /// <param name="change">the text change to apply</param>
/// <param name="newSelection">new position or selection, null if normal position after text changes</param>
/// <returns>true if successed</returns>
- public abstract bool TryGetCompletionForCurrentToken (object suggestion, out TextChange change, out TextSpan? newSelection);
- protected bool previousTokHasFlag(TokenType flag) => previousToken.HasValue && previousToken.Value.Type.HasFlag(flag);
+ public abstract bool TryCompleteToken (Token CurrentToken, SyntaxNode CurrentNode, object suggestion, out TextChange change, out TextSpan? newSelection);
+ //protected bool previousTokHasFlag(TokenType flag) => previousToken.HasValue && previousToken.Value.Type.HasFlag(flag);
void parse () {
- Tokenizer tokenizer = CreateTokenizer ();
- tokens = tokenizer?.Tokenize (source);
SyntaxAnalyser syntaxAnalyser = CreateSyntaxAnalyser ();
- Stopwatch sw = Stopwatch.StartNew ();
- syntaxAnalyser?.Process ();
- sw.Stop();
- root = syntaxAnalyser?.Root;
+ root = syntaxAnalyser?.Process ();
+ NotifyValueChanged("Exceptions", syntaxAnalyser?.Exceptions);
//CrowEditBase.App.Log (LogType.Low, $"Syntax Analysis done in {sw.ElapsedMilliseconds}(ms) {sw.ElapsedTicks}(ticks)");
- if (syntaxAnalyser == null)
- return;
- /*foreach (Token t in Tokens)
- Console.WriteLine ($"{t,-40} {Source.AsSpan(t.Start, t.Length).ToString()}");
- syntaxAnalyser.Root.Dump();*/
}
}
using System;
using System.Collections.Generic;
using System.Linq;
+using Crow.Text;
namespace CrowEditBase
{
public abstract class SyntaxAnalyser {
//protected abstract void Parse(SyntaxNode node);
- protected SourceDocument source;
- public SyntaxRootNode Root { get; protected set; }
+ protected ReadOnlyMemory<char> source;
+ protected LineCollection lines;
+ protected SyntaxRootNode Root;
public IEnumerable<SyntaxException> Exceptions => Root?.GetAllExceptions();
- public SyntaxAnalyser (SourceDocument source) {
- this.source = source;
+ public SyntaxAnalyser (SourceDocument document) {
+ this.source = document.ImmutableBufferCopy;
+ this.lines = document.Lines;
}
- public abstract void Process ();
+ public abstract SyntaxRootNode Process ();
#region Token handling
protected Token curTok => tokIdx < 0 ? default : tokens[tokIdx];
- protected Token[] tokens;
+ protected ReadOnlySpan<char> curTokString => curTok.AsString(source.Span);
+ protected ReadOnlySpan<Token> tokens => Root.Tokens;
protected bool EOF => tokIdx == tokens.Length;
protected bool tryRead (out Token tok) {
if (EOF) {
#endregion
#region parsing context
- protected int currentLine, tokIdx;
+ protected int currentLine = 0, tokIdx = 0;
protected SyntaxNode currentNode;
#endregion
/// </summary>
/// <param name="endToken">The final token of this node</param>
/// <param name="endLine">the endline number of this node</param>
- protected void setEndLineForCurrentNode (int endTokenOffsetFromCurrentTokIdx = 0) {
- currentNode.TokenCount = tokIdx - currentNode.TokenIndexBase + endTokenOffsetFromCurrentTokIdx;
+ protected void finishCurrentNode (int endTokenOffsetFromCurrentTokIdx = 0) {
+ int count = tokIdx - currentNode.TokenIndexBase + endTokenOffsetFromCurrentTokIdx;
+ currentNode.TokenCount = count < 0 ? null : count;
+ if (endTokenOffsetFromCurrentTokIdx < 0) {
+ Token lastTok = currentNode.LastTokenIndex.HasValue ?
+ Root.GetTokenByIndex(currentNode.LastTokenIndex.Value) :
+ Root.GetTokenByIndex(currentNode.TokenIndexBase);
+ currentNode.EndLine = lines.GetLocation(lastTok.End).Line;
+ }
+ //currentNode.EndLine
currentNode.EndLine = currentLine;
currentNode = currentNode.Parent;
}
- protected void setEndOfNode (int endTokenOffsetFromCurrentTokIdx = 0, int endLineOffsetFromCurrentLine = 0) {
+ /*protected void setEndOfNode (int endTokenOffsetFromCurrentTokIdx = 0, int endLineOffsetFromCurrentLine = 0) {
currentNode.TokenCount = tokIdx - currentNode.TokenIndexBase + endTokenOffsetFromCurrentTokIdx;
currentNode.EndLine = currentLine + endLineOffsetFromCurrentLine;
- }
+ }*/
protected void setCurrentNodeEndLine (int endLine)
=> currentNode.EndLine = endLine;
protected bool skipTrivia(bool skipLineBreaks = true) {
return !EOF;
}
protected void addException(string message) {
- currentNode.AddException(new SyntaxException(message, curTok));
+ currentNode.AddException(new SyntaxException(message, curTok, source));
}
{
public class SyntaxException : Exception {
public readonly Token Token;
- public readonly SyntaxAnalyser SyntaxAnalyser;
- public SyntaxException(string message, Token token = default, SyntaxAnalyser syntaxAnalyser = null, Exception innerException = null)
+ public readonly ReadOnlyMemory<char> SourceText;
+ public SyntaxException(string message, Token token = default, ReadOnlyMemory<char> textBuffer = default, Exception innerException = null)
: base (message, innerException) {
Token = token;
- SyntaxAnalyser = syntaxAnalyser;
+ SourceText = textBuffer;
}
- public string TokenString => SyntaxAnalyser.Root.GetTokenString(Token);
+ public string TokenString => SourceText.Span.Slice(Token.Start,Token.Length).ToString();
public override string ToString() => $"{Message}: {TokenString}";
}
}
\ No newline at end of file
return Span.Length < 0 ? "" : Root.GetText(Span).ToString();
}
public bool IsSimilar (SyntaxNode other) => this.GetType() == other?.GetType();
+
}
}
\ No newline at end of file
namespace CrowEditBase
{
public abstract class SyntaxRootNode : SyntaxNode {
- protected readonly SourceDocument source;
- public SyntaxRootNode (SourceDocument source) {
+ public SyntaxRootNode (ReadOnlyMemory<char> source, Token[] tokens) {
this.source = source;
+ this.tokens = tokens;
}
+ protected readonly ReadOnlyMemory<char> source;
+ protected Token[] tokens;
public override int TokenIndexBase => 0;
- public override int? TokenCount { get => Math.Max (0, source.Tokens.Length - 1); internal set {} }
+ public override int? TokenCount { get => tokens == null ? default : Math.Max (0, tokens.Length - 1); internal set {} }
public override SyntaxRootNode Root => this;
public override bool IsFoldable => false;
public override SyntaxNode NextSiblingOrParentsNextSibling => null;
public override void UnfoldToTheTop() {}
- public string GetTokenStringByIndex (int idx) =>
- idx >= 0 && idx < source.Tokens.Length ? Root.GetText(source.Tokens[idx].Span).ToString() : null;
- public Token GetTokenByIndex (int idx) =>
- idx >= 0 && idx < source.Tokens.Length ? source.Tokens[idx] : default;
+
+ public ReadOnlySpan<Token> Tokens => tokens;
+ public string GetTokenStringByIndex (int idx) => tokens != null ?
+ idx >= 0 && idx < tokens.Length ? GetText(tokens[idx].Span).ToString() : null : null;
+ public Token GetTokenByIndex (int idx) => tokens != null ?
+ idx >= 0 && idx < tokens.Length ? tokens[idx] : default : default;
public ReadOnlySpan<char> GetText(TextSpan span) =>
- source.GetText(span);
+ source.Span.Slice(span.Start, span.Length);
public string GetTokenString(Token tok) =>
- source.GetText(tok.Span).ToString();
+ GetText(tok.Span).ToString();
}
}
\ No newline at end of file
namespace CrowEditBase
{
+ public static class Extensions {
+ public static bool TryCast<T>(this object o, out T result) {
+ result = default;
+ if (o != null) {
+ Type tIn = o.GetType();
+ Type tOut = typeof(T);
+ if (tOut.IsAssignableFrom(tIn)) {
+ result = (T)o;
+ return true;
+ }
+ }
+ return false;
+ }
+ }
public abstract class CrowEditBase : Interface {
public static CrowEditBase App;
public CrowEditBase (int width, int height, bool singleThreaded = true) : base (width, height, singleThreaded) {
public void ExitWriteLock () => documentRWLock.ExitWriteLock ();
public abstract bool TryGetState<T> (object client, out T state);
- public abstract void RegisterClient (object client);
+ public abstract void RegisterClient (object client, bool initialState = false);
public abstract void UnregisterClient (object client);
DateTime accessTime;
/// </summary>
/// <param name="position">Absolute character position in text.</param>
public void SetCursorPosition (int position) {
+ document.EnterReadLock();
CharLocation loc = document.GetLocation (position);
loc.Column = Math.Min (loc.Column, document.GetLine (loc.Line).Length);
+ document.ExitReadLock();
CurrentLoc = loc;
}
bool selectionNotEmpty = false;
document.EnterReadLock();
+
try {
//if (HasFocus) {
if (currentLoc?.Column < 0) {
protected void updateLocation (IContext gr, ref CharLocation loc) {
if (loc.HasVisualX)
return;
- TextLine ls = document.GetLine (loc.Line);
- ReadOnlySpan<char> curLine = document.GetText (ls);
-
+
+ ReadOnlySpan<char> curLine = document.GetLineText (loc.Line);
if (loc.Column >= 0) {
//int encodedBytes = Crow.Text.Encoding2.ToUtf8 (curLine.Slice (0, loc.Column), bytes);
#if DEBUG
int totChar = 0;
double cPos = 0;
- for (int i = 0; i < ls.Length; i++) {
+ for (int i = 0; i < curLine.Length; i++) {
int encodedBytes = curLine.Slice (i, 1).ToUtf8 (bytes, ref totChar, tabSize);
bytes[encodedBytes] = 0;
cPos += te.XAdvance;
}
- loc.Column = ls.Length;
+ loc.Column = curLine.Length;
loc.VisualCharXPosition = cPos;
loc.TabulatedColumn = totChar;
}
namespace Crow
{
public class SourceEditor : Editor {
- object TokenMutex = new object();
+ int currentTokenIndex = -1;
SyntaxNode currentNode;
#if DEBUG_NODE
SyntaxNode _hoverNode;
return;
currentNode = value;
NotifyValueChanged ("CurrentNode", currentNode);
- RegisterForRedraw ();
}
}
+
+ public Token CurrentToken => typeof(SourceDocument).IsAssignableFrom(Document?.GetType()) ?
+ (Document as SourceDocument).GetTokenByIndex(currentTokenIndex) : default;
#region suggestions and autocomplete
ListBox overlay;
protected void tryGetSuggestions () {
if (currentLoc.HasValue && Document is SourceDocument srcDoc && srcDoc.IsParsed) {
- IList suggs = srcDoc.GetSuggestions (CurrentLoc.Value);
+ IList suggs = srcDoc.GetSuggestions (CurrentToken, currentNode, CurrentLoc.Value);
+ Token tok = CurrentToken;
if (suggs != null && suggs.Count == 1 && (
- (suggs[0] is System.Reflection.MemberInfo mi && mi.Name == srcDoc.CurrentTokenString) ||
- (suggs[0].ToString() == srcDoc.CurrentTokenString)
+ (suggs[0] is System.Reflection.MemberInfo mi && mi.Name == srcDoc.GetText(tok.Span)) ||
+ (suggs[0].ToString() == srcDoc.GetText(tok.Span))
)){
Suggestions = null;
}else
}
void completeToken () {
if (Document is SourceDocument srcDoc) {
- if (srcDoc.TryGetCompletionForCurrentToken (overlay.SelectedItem, out TextChange change, out TextSpan? nextSelection)) {
+ if (srcDoc.TryCompleteToken (CurrentToken, CurrentNode, overlay.SelectedItem, out TextChange change, out TextSpan? nextSelection)) {
update (change);
if (nextSelection.HasValue) {
Selection = nextSelection.Value;
while (fold != null && fold.StartLine == currentLoc.Value.Line)
fold = fold.Parent;
fold?.UnfoldToTheTop();
- if (Document is SourceDocument doc)
- doc.updateCurrentTokAndNode (currentLoc.Value);
+ updateCurrentTokAndNode();
}
NotifyValueChanged ("CurrentLine", CurrentLine);
NotifyValueChanged ("CurrentColumn", CurrentColumn);
}
protected override void drawContent (IContext gr) {
- if (!(Document is SourceDocument doc)) {
+ if (!(Document is SourceDocument doc && doc.Root != null)) {
base.drawContent (gr);
return;
}
marginRect.Height = lineHeight;
cb.Left += leftMargin;
-
CharLocation selStart = default, selEnd = default;
bool selectionNotEmpty = false;
CharLocation? nodeStart = null, nodeEnd = null;
gr.ShowText (bytes.Slice (0, encodedBytes));
}
- if (doc.CurrentToken.Equals(tok)) {
+ if (CurrentToken.Equals(tok)) {
/*CharLocation? tokloc = Document.GetLocation (tok.Start);
updateLocation (gr, cb.Width, ref tokloc);*/
Rectangle r = new RectangleD(pixX, pixY, extents.Width, lineHeight);
protected override void update (TextChange change) {
base.update (change);
- if (Document is SourceDocument srcdoc)
- srcdoc.updateCurrentTokAndNode (CurrentLoc.Value);
+ updateCurrentTokAndNode();
if (!disableSuggestions &&!disableTextChangedEvent && HasFocus)
tryGetSuggestions ();
}
//Console.WriteLine ($"{pos}: {suggestionTok.AsString (_text)} {suggestionTok}");
}
-
+ void updateCurrentTokAndNode() {
+ if (currentLoc.HasValue && Document is SourceDocument srcdoc) {
+ currentTokenIndex = srcdoc.GetAbsolutePosition(currentLoc.Value);
+ Token tok = srcdoc.FindTokenIncludingPosition(currentTokenIndex);
+ CurrentNode = srcdoc.Root?.FindNodeIncludingSpan(tok.Span);
+
+ NotifyValueChanged("CurrentToken",tok);
+ } else {
+ currentTokenIndex = -1;
+ CurrentNode = null;
+ NotifyValueChanged("CurrentToken",default);
+ }
+ }
}
}
\ No newline at end of file
public bool mixedLineBreak = false;
public string lineBreak = null;
+ internal LineCollection GetLineListCopy() => new LineCollection(lines.ToArray());
public Span<char> Span => buffer.Span.Slice(0, length);
public ReadOnlySpan<char> ReadOnlySpan => buffer.Span.Slice(0, length);
public bool IsEmpty => length == 0;
- public bool IsDirty => origBuffer.Span.Equals(buffer.Span, StringComparison.Ordinal);
+ public bool IsDirty => !origBuffer.Span.Equals(Span, StringComparison.Ordinal);
public int LinesCount => lines.Count;
public int Length => length;
public ReadOnlyMemory<char> ReadOnlyCopy {
}
}
public void ResetDirtyState () {
- origBuffer = buffer.ToArray();
+ origBuffer = Span.ToArray();
}
public TextBuffer(ReadOnlySpan<char> origText) {
length = origText.Length;
lines.Add (new TextLine (0, 0, 0));
else
lines.Update (Span);
+ ResetDirtyState ();
}
public void Update (TextChange change) {
ReadOnlySpan<char> orig = buffer.Span;
}
public CharLocation GetLocation (int absolutePosition) => lines.GetLocation (absolutePosition);
public TextLine GetLine (int index) => lines[index];
+ public ReadOnlySpan<char> GetText (TextLine line) => GetText(line.Span);
+ public ReadOnlySpan<char> GetText (TextSpan textSpan) => buffer.Span.Slice(textSpan.Start, textSpan.Length);
public int GetAbsolutePosition (CharLocation loc) => lines.GetAbsolutePosition (loc);
public CharLocation EndLocation => new CharLocation (lines.Count - 1, lines[lines.Count - 1].Length);
public override string ToString() => ReadOnlySpan.ToString();
protected TextBuffer buffer;
public ReadOnlySpan<char> source => buffer.ReadOnlySpan;
+ public ReadOnlyMemory<char> ImmutableBufferCopy => buffer.ReadOnlyCopy;
+ internal LineCollection Lines => buffer.GetLineListCopy();
System.Text.Encoding encoding = System.Text.Encoding.UTF8;
public override bool IsDirty => buffer.IsDirty;
}
return state != null;
}
- public override void RegisterClient(object client)
+ public override void RegisterClient(object client, bool initState = false)
{
- documentRWLock.EnterWriteLock ();
+ EnterWriteLock();
registeredClients.Add (client, null);
- //notifyClient (client, new TextChange (0, 0, source));
- documentRWLock.ExitWriteLock ();
+ if (initState)
+ notifyClient (client,new TextChange (0, 0,source.ToString()));
+ ExitWriteLock();
}
public override void UnregisterClient(object client)
{
- documentRWLock.EnterWriteLock ();
+ EnterWriteLock();
registeredClients.Remove (client);
- documentRWLock.ExitWriteLock ();
+ ExitWriteLock();
}
void notifyClients (TextChange tc, object triggeringClient = null) {
object[] clients = registeredClients.Keys.ToArray ();
encoding = sr.CurrentEncoding;
}
}
- ReadOnlyMemory<char> testbuff = buffer.ReadOnlyCopy;
-
- buffer.Update(new TextChange(0,0,"test"));
-
- Debug.WriteLine($"buffer: {buffer.ToString()}");
- Debug.WriteLine($"testbuff: {testbuff.ToString()}");
}
protected override void initNewFile()
{
documentRWLock.ExitReadLock();
}
}
+ public ReadOnlySpan<char> GetLineText (int index) {
+ documentRWLock.EnterReadLock ();
+ try {
+ return buffer.GetText (buffer.GetLine(index));
+ } finally {
+ documentRWLock.ExitReadLock();
+ }
+ }
public ReadOnlySpan<char> GetText (TextLine line) {
documentRWLock.EnterReadLock ();
try {
- return source.GetLine (line);
+ return buffer.GetText (line);
} finally {
documentRWLock.ExitReadLock();
}
public ReadOnlySpan<char> GetText (TextSpan span) {
documentRWLock.EnterReadLock ();
try {
- return source.Slice (span.Start, span.Length);
+ return buffer.GetText (span);
} finally {
documentRWLock.ExitReadLock();
}
<IntermediateOutputPath>$(SolutionDir)build\obj\$(Configuration)\</IntermediateOutputPath>
<License>MIT</License>
<Authors>Jean-Philippe Bruyère</Authors>
- <LangVersion>7.2</LangVersion>
+ <!--<LangVersion>7.2</LangVersion>-->
</PropertyGroup>
</Project>
if (value is ImlDocument imlDoc) {
document?.UnregisterClient (this);
- imlSource = "";
document = imlDoc;
- document?.RegisterClient (this);
+ imlSource = default;
+ document?.RegisterClient (this, true);
NotifyValueChangedAuto (document);
RegisterForGraphicUpdate ();
if (msbp.IsCrowProject)
}*/
}
- protected override Tokenizer CreateTokenizer() => new ImlTokenizer ();
protected override SyntaxAnalyser CreateSyntaxAnalyser() => new ImlSyntaxAnalyser (this);
public override string GetTokenTypeString (TokenType tokenType) => ((ImlTokenType)tokenType).ToString();
Type crowType = IML.Instantiator.GetWidgetTypeFromName (crowTypeName);
return crowType.GetMember (memberName, BindingFlags.Public | BindingFlags.Instance).FirstOrDefault ();
}
-
- protected bool previousTokHasFlag(ImlTokenType flag) => previousToken.HasValue && previousToken.Value.Type.HasFlag(flag);
-
- protected bool tryCast<TOUT> (object objectToCast, out TOUT result) {
- result = default;
- if (typeof(TOUT).IsAssignableFrom(objectToCast.GetType())) {
- result = (TOUT)objectToCast;
- return true;
- }
- return false;
- }
- public override IList GetSuggestions (CharLocation loc) {
- IList sugs = base.GetSuggestions (loc);
+ public override IList GetSuggestions (Token currentToken, SyntaxNode CurrentNode, CharLocation loc) {
+ IList sugs = base.GetSuggestions (currentToken, CurrentNode, loc);
if (sugs != null)
return sugs;
return new List<string> (allWidgetNames);
if (tok.GetTokenType() == XmlTokenType.ElementName)
return allWidgetNames.Where (s => s.StartsWith (root.GetTokenString(tok), StringComparison.OrdinalIgnoreCase)).ToList ();
- if ((tok.Type.HasFlag(TokenType.WhiteSpace) || previousTokHasFlag(TokenType.WhiteSpace)) &&
- tryCast(CurrentNode, out ElementTagSyntax ets)) {
+ if (tok.Type.HasFlag(TokenType.WhiteSpace) && CurrentNode.TryCast(out ElementTagSyntax ets)) {
if (ets.name.HasValue)
return getAllCrowTypeMembers (ets.Name).ToList();
return null;
}*/
return null;
}
- public override bool TryGetCompletionForCurrentToken (object suggestion, out TextChange change, out TextSpan? newSelection) {
- return base.TryGetCompletionForCurrentToken (suggestion is MemberInfo mi ? mi.Name : suggestion, out change, out newSelection);
+ public override bool TryCompleteToken (Token tok, SyntaxNode node, object suggestion, out TextChange change, out TextSpan? newSelection) {
+ return base.TryCompleteToken (tok, node, suggestion is MemberInfo mi ? mi.Name : suggestion, out change, out newSelection);
}
public override Color GetColorForToken(TokenType tokType)
namespace CECrowPlugin
{
public class ImlSyntaxAnalyser : XmlSyntaxAnalyser {
- public ImlSyntaxAnalyser (ImlDocument source) : base (source) {
- this.source = source;
- }
+ public ImlSyntaxAnalyser (ImlDocument document) : base (document) {}
- public override void Process () {
+ public override SyntaxRootNode Process () {
- base.Process();
+ return base.Process();
/*
ImlDocument xmlDoc = source as ImlDocument;
}*/
}
- protected override Tokenizer CreateTokenizer() => new StyleTokenizer ();
protected override SyntaxAnalyser CreateSyntaxAnalyser() => new StyleSyntaxAnalyser (this);
- public override IList GetSuggestions (CharLocation loc) {
- Console.ForegroundColor = ConsoleColor.DarkYellow;
+ public override IList GetSuggestions (Token currentToken, SyntaxNode CurrentNode, CharLocation loc) {
+ /*Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine ($"Tok: {this.CurrentTokenString} {((StyleTokenType)CurrentToken.Type).ToString()}");
- Console.ResetColor();
+ Console.ResetColor();*/
return null;
}
- public override bool TryGetCompletionForCurrentToken(object suggestion, out TextChange change, out TextSpan? newSelection)
+ public override bool TryCompleteToken(Token tok, SyntaxNode node, object suggestion, out TextChange change, out TextSpan? newSelection)
{
change = default;
newSelection = null;
}
}
public class StyleSyntaxAnalyser : SyntaxAnalyser {
- public StyleSyntaxAnalyser (StyleDocument source) : base (source) {
- this.source = source;
- }
+ public StyleSyntaxAnalyser (StyleDocument document) : base (document) {}
+
+ public override SyntaxRootNode Process () {
+ Tokenizer tokenizer = new StyleTokenizer();
+ Token[] tokens = tokenizer.Tokenize(source.Span);
+
+ currentNode = Root = new StyleRootSyntax (source, tokens);
- public override void Process () {
- StyleDocument doc = source as StyleDocument;
- currentNode = Root = new StyleRootSyntax (doc);
currentLine = 0;
- Span<Token> toks = source.Tokens;
tokIdx = 0;
int firstNameIdx = -1;
- while (tokIdx < toks.Length) {
- Token curTok = toks[tokIdx];
+ while (tokIdx < tokens.Length) {
+ Token curTok = tokens[tokIdx];
if (curTok.Type == TokenType.LineBreak)
currentLine++;
else if (!curTok.Type.HasFlag (TokenType.Trivia)) {
}
while (currentNode.Parent != null) {
if (!currentNode.TokenCount.HasValue)
- setEndLineForCurrentNode (-1);
+ finishCurrentNode (-1);
else
currentNode = currentNode.Parent;
}
setCurrentNodeEndLine (currentLine);
+
+ return Root;
}
}
}
\ No newline at end of file
{
public class StyleRootSyntax : SyntaxRootNode {
- public StyleRootSyntax (StyleDocument source)
- : base (source) {
- }
+ public StyleRootSyntax (ReadOnlyMemory<char> source, Token[] tokens) : base (source, tokens) { }
}
public class ConstantDefinitionSyntax : SyntaxNode {
internal int? name, equal, valueOpen, valueClose;
//
// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
using Crow.Text;
using System.Collections;
using CrowEditBase;
public EbnfDocument (string fullPath, string editorPath) : base (fullPath, editorPath) {
}
- protected override Tokenizer CreateTokenizer() => new EbnfTokenizer ();
protected override SyntaxAnalyser CreateSyntaxAnalyser() => new EbnfSyntaxAnalyser (this);
- public override IList GetSuggestions (CharLocation loc) {
+ public override IList GetSuggestions (Token currentToken, SyntaxNode CurrentNode, CharLocation loc) {
return null;
}
- public override bool TryGetCompletionForCurrentToken (object suggestion, out TextChange change, out TextSpan? newSelection) {
+ public override bool TryCompleteToken (Token tok, SyntaxNode node, object suggestion, out TextChange change, out TextSpan? newSelection) {
newSelection = null;
change = default;
return false;
{
public class EbnfSyntaxAnalyser : SyntaxAnalyser {
- public EbnfSyntaxAnalyser (EbnfDocument source) : base (source) {
- this.source = source;
- }
+ public EbnfSyntaxAnalyser (EbnfDocument document) : base (document) {}
// ::= NCName '::=' Expression
// Item ::= Primary ( '?' | '*' | '+' )?
//NCName | StringLiteral | CharCode | CharClass | '(' Choice ')'
// StringLiteral ::= '"' [^"]* '"' | "'" [^']* "'"
-
- public override void Process()
+
+ public override SyntaxRootNode Process()
{
- EbnfDocument doc = source as EbnfDocument;
- currentNode = Root = new EbnfRootSyntax (doc);
+ Tokenizer tokenizer = new EbnfTokenizer();
+ Token[] tokens = tokenizer.Tokenize(source.Span);
+
+ currentNode = Root = new EbnfRootSyntax (source, tokens);
currentLine = 0;
tokIdx = 0;
- tokens = doc.Tokens;
/*while(tokIdx < tokens.Length) {
skipTrivia();
setCurrentNodeEndLine (currentLine);
+ return Root;
}
{
public class EbnfRootSyntax : SyntaxRootNode {
- public EbnfRootSyntax (EbnfDocument source)
- : base (source) {
- }
+ public EbnfRootSyntax (ReadOnlyMemory<char> source, Token[] tokens) : base (source, tokens) { }
}
public class EbnfSyntaxNode : SyntaxNode {
public EbnfSyntaxNode(int startLine, int tokenBase)
}
#region SourceDocument abstract class implementation
- protected override Tokenizer CreateTokenizer() => new CSTokenizer ();
protected override SyntaxAnalyser CreateSyntaxAnalyser() => new CSSyntaxAnalyser (this);
- public override IList GetSuggestions (CharLocation loc)
+ public override IList GetSuggestions (Token currentToken, SyntaxNode CurrentNode, CharLocation loc)
{
throw new NotImplementedException();
}
- public override bool TryGetCompletionForCurrentToken (object suggestion, out TextChange change, out TextSpan? newSelection)
+ public override bool TryCompleteToken (Token tok, SyntaxNode node, object suggestion, out TextChange change, out TextSpan? newSelection)
{
throw new NotImplementedException();
}
namespace CERoslynPlugin
{
public class CSRootSyntax : SyntaxRootNode {
- public CSRootSyntax (SourceDocument source)
- : base (source) {
- }
+ public CSRootSyntax (ReadOnlyMemory<char> source, Token[] tokens) : base (source, tokens) { }
}
+
public class CSSyntaxAnalyser : SyntaxAnalyser {
/*protected override void Parse(SyntaxNode node)
{
throw new NotImplementedException();
}*/
- public CSSyntaxAnalyser (CSDocument source) : base (source) {
- this.source = source;
- }
+ public CSSyntaxAnalyser (CSDocument document) : base (document) {}
+
+ public override SyntaxRootNode Process () {
+ Tokenizer tokenizer = new CSTokenizer();
+ Token[] tokens = tokenizer.Tokenize(source.Span);
- public override void Process () {
- currentNode = Root = new CSRootSyntax (source);
+ currentNode = Root = new CSRootSyntax (source, tokens);
+ return Root;
}
}
}
\ No newline at end of file
using CrowEditBase;
using Drawing2D;
using System.Collections.Generic;
+using System;
namespace CrowEdit.Xml
{
public static void SetTokenType (this Token tok, XmlTokenType type) {
tok.Type = (TokenType)type;
}
+
}
public class XmlDocument : SourceDocument {
- public XmlDocument (string fullPath, string editorPath) : base (fullPath, editorPath) {
-
- }
- protected override Tokenizer CreateTokenizer() => new XmlTokenizer ();
+ public XmlDocument (string fullPath, string editorPath) : base (fullPath, editorPath) { }
protected override SyntaxAnalyser CreateSyntaxAnalyser() => new XmlSyntaxAnalyser (this);
public override string GetTokenTypeString (TokenType tokenType) => ((XmlTokenType)tokenType).ToString();
- public override IList GetSuggestions (CharLocation loc) {
+ public override IList GetSuggestions (Token currentToken, SyntaxNode CurrentNode, CharLocation loc) {
/*currentToken = FindTokenIncludingPosition (pos);
currentNode = FindNodeIncludingPosition (pos);*/
if (currentToken.GetTokenType() == XmlTokenType.EndElementOpen &&
}
return null;
}
- public override bool TryGetCompletionForCurrentToken (object suggestion, out TextChange change, out TextSpan? newSelection) {
+ public override bool TryCompleteToken (Token tok, SyntaxNode node, object suggestion, out TextChange change, out TextSpan? newSelection) {
newSelection = null;
change = default;
if (selectedSugg == null)
return false;
- Token tok = CurrentToken;
XmlTokenType tokType = tok.GetTokenType();
if (tokType.HasFlag(XmlTokenType.WhiteSpace)) {
- if (typeof(ElementTagSyntax).IsAssignableFrom(CurrentNode?.GetType())) {
- ElementTagSyntax ets = CurrentNode as ElementTagSyntax;
+
+ if (typeof(ElementTagSyntax).IsAssignableFrom(node?.GetType())) {
+ ElementTagSyntax ets = node as ElementTagSyntax;
if (ets.name.HasValue) {
- change = new TextChange (currentToken.End, 0, selectedSugg + "=\"\"");
+ change = new TextChange (tok.End, 0, selectedSugg + "=\"\"");
newSelection = TextSpan.FromStartAndLength(change.End2 - 1);
} else
- change = new TextChange (currentToken.End, 0, selectedSugg + " ");
+ change = new TextChange (tok.End, 0, selectedSugg + " ");
} else {
- change = new TextChange (currentToken.End, 0, selectedSugg);
+ change = new TextChange (tok.End, 0, selectedSugg);
}
} else if (tokType == XmlTokenType.EndElementOpen) {
- change = new TextChange (currentToken.End, 0, selectedSugg + ">");
+ change = new TextChange (tok.End, 0, selectedSugg + ">");
} else if (tokType == XmlTokenType.ElementName) {
- if (CurrentNode is ElementEndTagSyntax)
- change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg + ">");
+ if (node is ElementEndTagSyntax)
+ change = new TextChange (tok.Start, tok.Length, selectedSugg + ">");
else {
- change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg + ">");
+ change = new TextChange (tok.Start, tok.Length, selectedSugg + ">");
newSelection = TextSpan.FromStartAndLength (change.End2 - 1);
}
- } else if (CurrentNode is AttributeSyntax attrib) {
+ } else if (node is AttributeSyntax attrib) {
if (tokType == XmlTokenType.AttributeName) {
if (attrib.ValueToken.HasValue) {
- change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg);
+ change = new TextChange (tok.Start, tok.Length, selectedSugg);
newSelection = new TextSpan(
attrib.ValueToken.Value.Start + change.CharDiff + 1,
attrib.ValueToken.Value.End + change.CharDiff - 1
);
} else {
- change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg + "=\"\"");
- newSelection = TextSpan.FromStartAndLength (currentToken.Start + selectedSugg.Length + 2);
+ change = new TextChange (tok.Start, tok.Length, selectedSugg + "=\"\"");
+ newSelection = TextSpan.FromStartAndLength (tok.Start + selectedSugg.Length + 2);
}
} else {
int offset = 1;
offset = 0;
}
if (tokType == XmlTokenType.AttributeValueOpen)
- change = new TextChange (currentToken.End, 0, selectedSugg);
+ change = new TextChange (tok.End, 0, selectedSugg);
else if (tokType == XmlTokenType.AttributeValue)
- change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg);
+ change = new TextChange (tok.Start, tok.Length, selectedSugg);
newSelection = TextSpan.FromStartAndLength (change.End2 + offset);
}
} else if (tokType == XmlTokenType.ElementOpen) {
- change = new TextChange (currentToken.End, 0, selectedSugg + " ");
+ change = new TextChange (tok.End, 0, selectedSugg + " ");
} else
- change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg);
+ change = new TextChange (tok.Start, tok.Length, selectedSugg);
return true;
/***********************************************/
- /*if (currentToken.GetTokenType() == XmlTokenType.ElementOpen ||
- currentToken.GetTokenType() == XmlTokenType.WhiteSpace ||
- currentToken.GetTokenType() == XmlTokenType.AttributeValueOpen) {
- change = new TextChange (currentToken.End, 0, selectedSugg);
+ /*if (tok.GetTokenType() == XmlTokenType.ElementOpen ||
+ tok.GetTokenType() == XmlTokenType.WhiteSpace ||
+ tok.GetTokenType() == XmlTokenType.AttributeValueOpen) {
+ change = new TextChange (tok.End, 0, selectedSugg);
return true;
}
- if (currentToken.GetTokenType() == XmlTokenType.AttributeName && CurrentNode is AttributeSyntax attrib) {
+ if (tok.GetTokenType() == XmlTokenType.AttributeName && CurrentNode is AttributeSyntax attrib) {
if (attrib.ValueToken.HasValue) {
- change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg);
+ change = new TextChange (tok.Start, tok.Length, selectedSugg);
newSelection = new TextSpan(
attrib.ValueToken.Value.Start + change.CharDiff + 1,
attrib.ValueToken.Value.End + change.CharDiff - 1
);
} else {
- change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg + "=\"\"");
- newSelection = TextSpan.FromStartAndLength (currentToken.Start + selectedSugg.Length + 2);
+ change = new TextChange (tok.Start, tok.Length, selectedSugg + "=\"\"");
+ newSelection = TextSpan.FromStartAndLength (tok.Start + selectedSugg.Length + 2);
}
return true;
}
- change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg);
+ change = new TextChange (tok.Start, tok.Length, selectedSugg);
return true;*/
}
return Colors.Red;
}
- protected bool previousTokHasFlag(XmlTokenType flag) => previousToken.HasValue && previousToken.Value.Type.HasFlag(flag);
+ //protected bool previousTokHasFlag(XmlTokenType flag) => previousToken.HasValue && previousToken.Value.Type.HasFlag(flag);
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Reflection.Metadata.Ecma335;
using CrowEditBase;
namespace CrowEdit.Xml
{
public class XmlSyntaxAnalyser : SyntaxAnalyser {
- public XmlSyntaxAnalyser (XmlDocument source) : base (source) {
- this.source = source;
- }
+ public XmlSyntaxAnalyser (XmlDocument document) : base (document) {}
public virtual void ProcessAttributeValueSyntax(AttributeSyntax attrib) {
attrib.valueTok = tokIdx - attrib.TokenIndexBase;
}
- public override void Process () {
- XmlDocument xmlDoc = source as XmlDocument;
- currentNode = Root = new XMLRootSyntax (xmlDoc);
+ public override SyntaxRootNode Process () {
+ Tokenizer tokenizer = new XmlTokenizer();
+ Token[] tokens = tokenizer.Tokenize(source.Span);
+
+ currentNode = Root = new XMLRootSyntax (source, tokens);
currentLine = 0;
tokIdx = 0;
- tokens = source.Tokens;
while (tokIdx < tokens.Length) {
if (curTok.Type == TokenType.LineBreak)
tag.name = tokIdx - tag.TokenIndexBase;
else if (curTok.GetTokenType() == XmlTokenType.ClosingSign) {
tag.close = tokIdx - tag.TokenIndexBase;
- setEndLineForCurrentNode ();
+ finishCurrentNode ();
currentNode.RemoveChild (tag);
currentNode = currentNode.AddChild (new ElementSyntax (tag));
} else if (curTok.GetTokenType() == XmlTokenType.EmptyElementClosing) {
- setEndLineForCurrentNode ();
+ finishCurrentNode ();
currentNode.RemoveChild (tag);
currentNode = currentNode.AddChild (new EmptyElementSyntax (tag));
setCurrentNodeEndLine (currentLine);
currentNode = currentNode.Parent;
} else {
addException ("Unexpected Token");
- setEndLineForCurrentNode (-1);
+ finishCurrentNode (-1);
continue;
}
} else if (currentNode is ElementSyntax elt) {
else if (curTok.GetTokenType() == XmlTokenType.EndElementOpen) {
elt.EndTag = new ElementEndTagSyntax (currentLine, tokIdx);
currentNode = elt.AddChild (elt.EndTag);
+ /*} else {
+ finishCurrentNode(-1);
+ addException ("Unmatching open/closing element name");
+ }*/
}
} else if (currentNode is AttributeSyntax attrib) {
if (curTok.GetTokenType() == XmlTokenType.EqualSign)
ProcessAttributeValueSyntax (attrib);
else if (curTok.GetTokenType() == XmlTokenType.AttributeValueClose) {
attrib.valueClose = tokIdx - attrib.TokenIndexBase;
- setEndLineForCurrentNode ();
+ finishCurrentNode ();
} else {
addException ("Unexpected Token");
- setEndLineForCurrentNode (-1);
+ finishCurrentNode (-1);
continue;
}
} else if (currentNode is ElementEndTagSyntax eltEndTag) {
else if (curTok.GetTokenType() == XmlTokenType.ClosingSign) {
eltEndTag.close = tokIdx - eltEndTag.TokenIndexBase;
//go up 2 times
- setEndLineForCurrentNode (); setEndLineForCurrentNode ();
+ finishCurrentNode (); finishCurrentNode ();
} else {
addException ("Unexpected Token");
- setEndLineForCurrentNode (-1);
- setEndLineForCurrentNode (-1);
+ finishCurrentNode (-1);
+ finishCurrentNode (-1);
continue;
}
} else if (currentNode is XMLRootSyntax) {
pi.name = tokIdx - pi.TokenIndexBase;
else if (curTok.GetTokenType() == XmlTokenType.PI_End) {
pi.PIClose = tokIdx - pi.TokenIndexBase;
- setEndLineForCurrentNode ();
+ finishCurrentNode ();
} else if (curTok.GetTokenType() == XmlTokenType.AttributeName) {
AttributeSyntax attribute = new AttributeSyntax (currentLine, tokIdx);
attribute.name = 0;
currentNode = currentNode.AddChild (attribute);
} else {
addException ("Unexpected Token");
- setEndLineForCurrentNode (-1);
+ finishCurrentNode (-1);
continue;
}
}
}
while (currentNode.Parent != null) {
if (!currentNode.TokenCount.HasValue)
- setEndLineForCurrentNode (-1);
+ finishCurrentNode (-1);
else
currentNode = currentNode.Parent;
}
setCurrentNodeEndLine (currentLine);
+ return Root;
}
}
}
\ No newline at end of file
// Copyright (c) 2013-2021 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 System.Linq;
using Crow.Text;
using CrowEditBase;
{
public class XMLRootSyntax : SyntaxRootNode {
- public XMLRootSyntax (XmlDocument source)
- : base (source) {
- }
+ public XMLRootSyntax (ReadOnlyMemory<char> source, Token[] tokens) : base (source, tokens) { }
}
public class ProcessingInstructionSyntax : SyntaxNode {
public int? PIClose, name;
<?xml version="1.0"?>
<DockWindow Style="DockWindow" Caption="Logs" Width="80%" Height="20%" >
<VerticalStack>
-
- <TabView Data="{OpenedLogs}" SelectedItem="{²CurrentLog}">
- <Template>
- <VerticalStack Spacing="0" >
- <HorizontalStack Height="Fit">
- <ListBox Data="{./Items}" >
- <Template>
- <VerticalStack Spacing="0" >
- <ScrollBar Orientation="Horizontal" Foreground="RoyalBlue" Height="6" Width="Stretched" CornerRadius="3"
- Value="{²../ItemsScroller.ScrollX}"
- LargeIncrement="{../ItemsScroller.PageWidth}" SmallIncrement="1"
- CursorRatio="{../ItemsScroller.ChildWidthRatio}" Maximum="{../ItemsScroller.MaxScrollX}">
- <Template>
- <Container Margin="1" Background="{./Background}">
- <Widget Name="Cursor" Background="{./Foreground}" CornerRadius="{./CornerRadius}"/>
- </Container>
- </Template>
- </ScrollBar>
- <Scroller Name="ItemsScroller" Height="Fit" Width="Stretched">
- <HorizontalStack Name="ItemsContainer" Width="Fit" HorizontalAlignment="Left"/>
- </Scroller>
- </VerticalStack>
- </Template>
- <ItemTemplate>
- <ListItem RootDataLevel="true" Fit="true" Background="${InactiveTabBackground}" Foreground="${InactiveTabForeground}" IsSelected="{IsVisible}"
- Selected="{.DataSource.IsVisible='true'};{Background=${SelectedTabBackground}};{Foreground=${SelectedTabForeground}}"
- Unselected="{.DataSource.IsVisible='false'};{Background=${InactiveTabBackground}};{Foreground=${InactiveTabForeground}}"
- BubbleEvents="MouseWheel">
- <HorizontalStack DataSource="{DataSource}" Margin="3" Spacing="5">
- <!--<Image Style="TreeIcon" Path="{Icon}" SvgSub="{IconSub}"/> No icon in Document class-->
- <Label Text="{Name}" ContextCommands="{TabCommands}" Foreground="{../../Foreground}" />
- <Border CornerRadius="5" BorderWidth="1" Foreground="Transparent" Height="12" Width="12"
- MouseEnter="{Foreground=White}" MouseLeave="{Foreground=Transparent}">
- <Image Focusable="true" Name="Image" Margin="0" Width="Stretched" Height="Stretched" Path="#Crow.Icons.exit2.svg"
- MouseClick="OnQueryClose"/>
- </Border>
- </HorizontalStack>
- </ListItem>
- </ItemTemplate>
- </ListBox>
- <Popper Caption="Available Logs">
- <ListBox Data="{Logs}" Style="ScrollingListBox" Height="100" Width="200" Background="Jet" BubbleEvents="none" >
+ <TabView Data="{OpenedLogs}" SelectedItem="{²CurrentLog}">
+ <Template>
+ <VerticalStack Spacing="0" >
+ <HorizontalStack Height="Fit">
+ <ListBox Data="{./Items}" >
+ <Template>
+ <VerticalStack Spacing="0" >
+ <ScrollBar Orientation="Horizontal" Foreground="RoyalBlue" Height="6" Width="Stretched" CornerRadius="3"
+ Value="{²../ItemsScroller.ScrollX}"
+ LargeIncrement="{../ItemsScroller.PageWidth}" SmallIncrement="1"
+ CursorRatio="{../ItemsScroller.ChildWidthRatio}" Maximum="{../ItemsScroller.MaxScrollX}">
+ <Template>
+ <Container Margin="1" Background="{./Background}">
+ <Widget Name="Cursor" Background="{./Foreground}" CornerRadius="{./CornerRadius}"/>
+ </Container>
+ </Template>
+ </ScrollBar>
+ <Scroller Name="ItemsScroller" Height="Fit" Width="Stretched">
+ <HorizontalStack Name="ItemsContainer" Width="Fit" HorizontalAlignment="Left"/>
+ </Scroller>
+ </VerticalStack>
+ </Template>
<ItemTemplate>
- <Border CornerRadius="2" Margin="0" Height="Fit"
- Foreground="Transparent"
- MouseEnter="{Foreground=DimGrey}"
- MouseLeave="{Foreground=Transparent}">
- <CheckBox Caption="{Name}" Width="Stretched" IsChecked="{²IsOpened}"/>
- </Border>
+ <ListItem RootDataLevel="true" Fit="true" Background="${InactiveTabBackground}" Foreground="${InactiveTabForeground}" IsSelected="{IsVisible}"
+ Selected="{.DataSource.IsVisible='true'};{Background=${SelectedTabBackground}};{Foreground=${SelectedTabForeground}}"
+ Unselected="{.DataSource.IsVisible='false'};{Background=${InactiveTabBackground}};{Foreground=${InactiveTabForeground}}"
+ BubbleEvents="MouseWheel">
+ <HorizontalStack DataSource="{DataSource}" Margin="3" Spacing="5">
+ <!--<Image Style="TreeIcon" Path="{Icon}" SvgSub="{IconSub}"/> No icon in Document class-->
+ <Label Text="{Name}" ContextCommands="{TabCommands}" Foreground="{../../Foreground}" />
+ <Border CornerRadius="5" BorderWidth="1" Foreground="Transparent" Height="12" Width="12"
+ MouseEnter="{Foreground=White}" MouseLeave="{Foreground=Transparent}">
+ <Image Focusable="true" Name="Image" Margin="0" Width="Stretched" Height="Stretched" Path="#Crow.Icons.exit2.svg"
+ MouseClick="OnQueryClose"/>
+ </Border>
+ </HorizontalStack>
+ </ListItem>
</ItemTemplate>
</ListBox>
- </Popper>
- </HorizontalStack>
- <Group Name="ItemsContainer" Background="${SelectedTabBackground}"/>
- </VerticalStack>
- </Template>
- <ItemTemplate>
- <ListItem IsVisible="{IsSelected}" IsSelected="{²IsSelected}">
- <VerticalStack RootDataLevel="true" >
- <HorizontalStack Height="Fit" Spacing="5" Margin="0">
- <Widget Width="Stretched"/>
- <EnumSelector Caption="Filter:" EnumValue="{²../../log.Filter}" />
- <TextBox Background="Grey" Foreground="Black" Text="{²../../log.SearchString}" Width="200" KeyDown="../../log.onSearch" Font="${SmallUIFont}"/>
- <CheckBox Fit="true" Caption="Case Sensitive" IsChecked="{²../../log.CaseSensitiveSearch}" Font="${SmallUIFont}"/>
- <CheckBox Fit="true" Caption="All Word" IsChecked="{²../../log.AllWordSearch}" Font="${SmallUIFont}"/>
- <Menu Style="DockWinTitleBarMenu" Data="{../../log.SearchCommands}" Fit="true" Background="Transparent"/>
- </HorizontalStack>
- <HorizontalStack Spacing="0">
- <LogViewerWidget Name="log" Logger="{}" Font="${SmallFont}" MaxScrollX="6000" ContextCommands="{Commands}" CurrentEntryIndex="{²SelectedIndex}"/>
- <ScrollBar Name="scrollbarY" Value="{²../log.ScrollY}" CursorRatio="{../log.ChildHeightRatio}" Maximum="{../log.MaxScrollY}" />
- </HorizontalStack>
- <ScrollBar Style="HScrollBar" Name="scrollbarX" Value="{²../log.ScrollX}" Maximum="{../log.MaxScrollX}" SmallIncrement="30"/>
- <HorizontalStack Height="Fit">
- <Label Text="MaxScrollY:"/>
- <Label Text="{../../log.MaxScrollY}"/>
- <Label Text="ScrollY:"/>
- <Label Text="{../../log.ScrollY}"/>
+ <Popper Caption="Available Logs">
+ <ListBox Data="{Logs}" Style="ScrollingListBox" Height="100" Width="200" Background="Jet" BubbleEvents="none" >
+ <ItemTemplate>
+ <Border CornerRadius="2" Margin="0" Height="Fit"
+ Foreground="Transparent"
+ MouseEnter="{Foreground=DimGrey}"
+ MouseLeave="{Foreground=Transparent}">
+ <CheckBox Caption="{Name}" Width="Stretched" IsChecked="{²IsOpened}"/>
+ </Border>
+ </ItemTemplate>
+ </ListBox>
+ </Popper>
</HorizontalStack>
+ <Group Name="ItemsContainer" Background="${SelectedTabBackground}"/>
</VerticalStack>
- </ListItem>
- </ItemTemplate>
- </TabView>
+ </Template>
+ <ItemTemplate>
+ <ListItem IsVisible="{IsSelected}" IsSelected="{²IsSelected}">
+ <VerticalStack RootDataLevel="true" >
+ <HorizontalStack Height="Fit" Spacing="5" Margin="0">
+ <Widget Width="Stretched"/>
+ <EnumSelector Caption="Filter:" EnumValue="{²../../log.Filter}" />
+ <TextBox Background="Grey" Foreground="Black" Text="{²../../log.SearchString}" Width="200" KeyDown="../../log.onSearch" Font="${SmallUIFont}"/>
+ <CheckBox Fit="true" Caption="Case Sensitive" IsChecked="{²../../log.CaseSensitiveSearch}" Font="${SmallUIFont}"/>
+ <CheckBox Fit="true" Caption="All Word" IsChecked="{²../../log.AllWordSearch}" Font="${SmallUIFont}"/>
+ <Menu Style="DockWinTitleBarMenu" Data="{../../log.SearchCommands}" Fit="true" Background="Transparent"/>
+ </HorizontalStack>
+ <HorizontalStack Spacing="0">
+ <LogViewerWidget Name="log" Logger="{}" Font="${SmallFont}" MaxScrollX="6000" ContextCommands="{Commands}" CurrentEntryIndex="{²SelectedIndex}"/>
+ <ScrollBar Name="scrollbarY" Value="{²../log.ScrollY}" CursorRatio="{../log.ChildHeightRatio}" Maximum="{../log.MaxScrollY}" />
+ </HorizontalStack>
+ <ScrollBar Style="HScrollBar" Name="scrollbarX" Value="{²../log.ScrollX}" Maximum="{../log.MaxScrollX}" SmallIncrement="30"/>
+ <HorizontalStack Height="Fit">
+ <Label Text="MaxScrollY:"/>
+ <Label Text="{../../log.MaxScrollY}"/>
+ <Label Text="ScrollY:"/>
+ <Label Text="{../../log.ScrollY}"/>
+ </HorizontalStack>
+ </VerticalStack>
+ </ListItem>
+ </ItemTemplate>
+ </TabView>
</VerticalStack>
</DockWindow>