</ItemGroup>
<ItemGroup>
<Compile Include="src\CrowIDE.cs" />
- <Compile Include="src\ImlVisualEditor.cs" />
<Compile Include="src\Extensions.cs" />
<Compile Include="src\Solution.cs" />
<Compile Include="src\Project.cs" />
<Link>src\InterfaceControler.cs</Link>
</Compile>
<Compile Include="src\DesignInterface.cs" />
- <Compile Include="src\EditPane.cs" />
<Compile Include="src\ProjectNodes.cs" />
<Compile Include="src\SolutionControler.cs" />
<Compile Include="src\INetProject.cs" />
- <Compile Include="src\SourceEditor\CodeBuffer.cs" />
- <Compile Include="src\SourceEditor\CodeBufferEventArgs.cs" />
- <Compile Include="src\SourceEditor\CodeLine.cs" />
- <Compile Include="src\SourceEditor\CSharpParser.cs" />
- <Compile Include="src\SourceEditor\Node.cs" />
- <Compile Include="src\SourceEditor\SourceEditor.cs" />
- <Compile Include="src\SourceEditor\TextFormatting.cs" />
- <Compile Include="src\SourceEditor\Token.cs" />
- <Compile Include="src\SourceEditor\XMLParser.cs" />
- <Compile Include="src\SourceEditor\StyleParser.cs" />
- <Compile Include="src\SourceEditor\BufferParser.cs" />
<Compile Include="src\MemberView\MembersView.cs" />
<Compile Include="src\MemberView\PropertyContainer.cs" />
<Compile Include="src\MemberView\CategoryContainer.cs" />
<Compile Include="src\GraphicObjectDesignContainer.cs" />
- <Compile Include="src\Editor.cs" />
- <Compile Include="src\SvgEditor.cs" />
+ <Compile Include="src\Editors\Editor.cs" />
+ <Compile Include="src\Editors\EditPane.cs" />
+ <Compile Include="src\Editors\ImlVisualEditor.cs" />
+ <Compile Include="src\Editors\SvgEditor.cs" />
+ <Compile Include="src\Editors\Parsers\BufferParser.cs" />
+ <Compile Include="src\Editors\Parsers\CSharpParser.cs" />
+ <Compile Include="src\Editors\Parsers\StyleParser.cs" />
+ <Compile Include="src\Editors\Parsers\XMLParser.cs" />
+ <Compile Include="src\Editors\CodeBuffer\CodeBuffer.cs" />
+ <Compile Include="src\Editors\CodeBuffer\CodeBufferEventArgs.cs" />
+ <Compile Include="src\Editors\CodeBuffer\CodeLine.cs" />
+ <Compile Include="src\Editors\CodeBuffer\Node.cs" />
+ <Compile Include="src\Editors\CodeBuffer\SourceEditor.cs" />
+ <Compile Include="src\Editors\CodeBuffer\TextFormatting.cs" />
+ <Compile Include="src\Editors\CodeBuffer\Token.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="ui\" />
<Folder Include="src\" />
<Folder Include="images\" />
- <Folder Include="src\SourceEditor\" />
<Folder Include="ui\ItemTemplates\" />
<Folder Include="src\MemberView\" />
<Folder Include="ui\DockWindows\" />
+ <Folder Include="ui\editors\" />
+ <Folder Include="src\Editors\" />
+ <Folder Include="src\Editors\Parsers\" />
+ <Folder Include="src\Editors\CodeBuffer\" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="images\save.svg" />
<LogicalName>Crow.TreeExpandable.template</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="ui\ProjectTree.template" />
- <EmbeddedResource Include="ui\EditPane.template">
- <LogicalName>Crow.Coding.EditPane.template</LogicalName>
- </EmbeddedResource>
- <EmbeddedResource Include="ui\EditPaneItems.template" />
<EmbeddedResource Include="ui\CrowIDE.crow" />
<EmbeddedResource Include="ui\icons\blank-file.svg" />
<EmbeddedResource Include="ui\icons\sign-out.svg" />
<LogicalName>Crow.MenuItem.template</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="ui\Options.crow" />
- <EmbeddedResource Include="ui\IMLEdit.itemp" />
- <EmbeddedResource Include="ui\SrcEdit.itemp" />
<EmbeddedResource Include="ui\IcoBut.template" />
<EmbeddedResource Include="ui\MembersItem.template" />
<EmbeddedResource Include="ui\ItemTemplates\Enum.template" />
<EmbeddedResource Include="icons\text-file.svg" />
<EmbeddedResource Include="icons\undo.svg" />
<EmbeddedResource Include="icons\redo.svg" />
- <EmbeddedResource Include="ui\SourceEditor.crow" />
+ <EmbeddedResource Include="ui\ContextMenu.template">
+ <LogicalName>Crow.ContextMenu.template</LogicalName>
+ </EmbeddedResource>
+ <EmbeddedResource Include="ui\editors\EditPane.template">
+ <LogicalName>Crow.Coding.EditPane.template</LogicalName>
+ </EmbeddedResource>
+ <EmbeddedResource Include="ui\editors\EditPaneItems.template">
+ <LogicalName>Crow.Coding.ui.EditPaneItems.template</LogicalName>
+ </EmbeddedResource>
+ <EmbeddedResource Include="ui\editors\IMLEdit.itemp">
+ <LogicalName>Crow.Coding.ui.IMLEdit.itemp</LogicalName>
+ </EmbeddedResource>
+ <EmbeddedResource Include="ui\editors\SourceEditor.crow">
+ <LogicalName>Crow.Coding.ui.SourceEditor.crow</LogicalName>
+ </EmbeddedResource>
+ <EmbeddedResource Include="ui\editors\SrcEdit.itemp">
+ <LogicalName>Crow.Coding.ui.SrcEdit.itemp</LogicalName>
+ </EmbeddedResource>
+ <EmbeddedResource Include="ui\editors\SvgEdit.itemp">
+ <LogicalName>Crow.Coding.ui.SvgEdit.itemp</LogicalName>
+ </EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="ui\test.crow">
<!-- Generated by IcoMoon.io -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16">
-<path fill="#444444" d="M12 7v-2l-1.2-0.4c-0.1-0.3-0.2-0.7-0.4-1l0.6-1.2-1.5-1.3-1.1 0.5c-0.3-0.2-0.6-0.3-1-0.4l-0.4-1.2h-2l-0.4 1.2c-0.3 0.1-0.7 0.2-1 0.4l-1.1-0.5-1.4 1.4 0.6 1.2c-0.2 0.3-0.3 0.6-0.4 1l-1.3 0.3v2l1.2 0.4c0.1 0.3 0.2 0.7 0.4 1l-0.5 1.1 1.4 1.4 1.2-0.6c0.3 0.2 0.6 0.3 1 0.4l0.3 1.3h2l0.4-1.2c0.3-0.1 0.7-0.2 1-0.4l1.2 0.6 1.4-1.4-0.6-1.2c0.2-0.3 0.3-0.6 0.4-1l1.2-0.4zM3 6c0-1.7 1.3-3 3-3s3 1.3 3 3c0 1.7-1.3 3-3 3s-3-1.3-3-3z"></path>
-<path fill="#444444" d="M7.5 6c0 0.828-0.672 1.5-1.5 1.5s-1.5-0.672-1.5-1.5c0-0.828 0.672-1.5 1.5-1.5s1.5 0.672 1.5 1.5z"></path>
-<path fill="#444444" d="M16 3v-1h-0.6c0-0.2-0.1-0.4-0.2-0.5l0.4-0.4-0.7-0.7-0.4 0.4c-0.2-0.1-0.3-0.2-0.5-0.2v-0.6h-1v0.6c-0.2 0-0.4 0.1-0.5 0.2l-0.4-0.4-0.7 0.7 0.4 0.4c-0.1 0.2-0.2 0.3-0.2 0.5h-0.6v1h0.6c0 0.2 0.1 0.4 0.2 0.5l-0.4 0.4 0.7 0.7 0.4-0.4c0.2 0.1 0.3 0.2 0.5 0.2v0.6h1v-0.6c0.2 0 0.4-0.1 0.5-0.2l0.4 0.4 0.7-0.7-0.4-0.4c0.1-0.2 0.2-0.3 0.2-0.5h0.6zM13.5 3.5c-0.6 0-1-0.4-1-1s0.4-1 1-1 1 0.4 1 1c0 0.6-0.4 1-1 1z"></path>
-<path fill="#444444" d="M15.4 11.8c-0.1-0.3-0.2-0.6-0.4-0.9l0.3-0.6-0.7-0.7-0.5 0.4c-0.3-0.2-0.6-0.3-0.9-0.4l-0.2-0.6h-1l-0.2 0.6c-0.3 0.1-0.6 0.2-0.9 0.4l-0.6-0.3-0.7 0.7 0.3 0.6c-0.2 0.3-0.3 0.6-0.4 0.9l-0.5 0.1v1l0.6 0.2c0.1 0.3 0.2 0.6 0.4 0.9l-0.3 0.6 0.7 0.7 0.6-0.3c0.3 0.2 0.6 0.3 0.9 0.4l0.1 0.5h1l0.2-0.6c0.3-0.1 0.6-0.2 0.9-0.4l0.6 0.3 0.7-0.7-0.4-0.5c0.2-0.3 0.3-0.6 0.4-0.9l0.6-0.2v-1l-0.6-0.2zM12.5 14c-0.8 0-1.5-0.7-1.5-1.5s0.7-1.5 1.5-1.5 1.5 0.7 1.5 1.5-0.7 1.5-1.5 1.5z"></path>
+<path fill="#FFFFFF" d="M12 7v-2l-1.2-0.4c-0.1-0.3-0.2-0.7-0.4-1l0.6-1.2-1.5-1.3-1.1 0.5c-0.3-0.2-0.6-0.3-1-0.4l-0.4-1.2h-2l-0.4 1.2c-0.3 0.1-0.7 0.2-1 0.4l-1.1-0.5-1.4 1.4 0.6 1.2c-0.2 0.3-0.3 0.6-0.4 1l-1.3 0.3v2l1.2 0.4c0.1 0.3 0.2 0.7 0.4 1l-0.5 1.1 1.4 1.4 1.2-0.6c0.3 0.2 0.6 0.3 1 0.4l0.3 1.3h2l0.4-1.2c0.3-0.1 0.7-0.2 1-0.4l1.2 0.6 1.4-1.4-0.6-1.2c0.2-0.3 0.3-0.6 0.4-1l1.2-0.4zM3 6c0-1.7 1.3-3 3-3s3 1.3 3 3c0 1.7-1.3 3-3 3s-3-1.3-3-3z"></path>
+<path fill="#FFFFFF" d="M7.5 6c0 0.828-0.672 1.5-1.5 1.5s-1.5-0.672-1.5-1.5c0-0.828 0.672-1.5 1.5-1.5s1.5 0.672 1.5 1.5z"></path>
+<path fill="#FFFFFF" d="M16 3v-1h-0.6c0-0.2-0.1-0.4-0.2-0.5l0.4-0.4-0.7-0.7-0.4 0.4c-0.2-0.1-0.3-0.2-0.5-0.2v-0.6h-1v0.6c-0.2 0-0.4 0.1-0.5 0.2l-0.4-0.4-0.7 0.7 0.4 0.4c-0.1 0.2-0.2 0.3-0.2 0.5h-0.6v1h0.6c0 0.2 0.1 0.4 0.2 0.5l-0.4 0.4 0.7 0.7 0.4-0.4c0.2 0.1 0.3 0.2 0.5 0.2v0.6h1v-0.6c0.2 0 0.4-0.1 0.5-0.2l0.4 0.4 0.7-0.7-0.4-0.4c0.1-0.2 0.2-0.3 0.2-0.5h0.6zM13.5 3.5c-0.6 0-1-0.4-1-1s0.4-1 1-1 1 0.4 1 1c0 0.6-0.4 1-1 1z"></path>
+<path fill="#FFFFFF" d="M15.4 11.8c-0.1-0.3-0.2-0.6-0.4-0.9l0.3-0.6-0.7-0.7-0.5 0.4c-0.3-0.2-0.6-0.3-0.9-0.4l-0.2-0.6h-1l-0.2 0.6c-0.3 0.1-0.6 0.2-0.9 0.4l-0.6-0.3-0.7 0.7 0.3 0.6c-0.2 0.3-0.3 0.6-0.4 0.9l-0.5 0.1v1l0.6 0.2c0.1 0.3 0.2 0.6 0.4 0.9l-0.3 0.6 0.7 0.7 0.6-0.3c0.3 0.2 0.6 0.3 0.9 0.4l0.1 0.5h1l0.2-0.6c0.3-0.1 0.6-0.2 0.9-0.4l0.6 0.3 0.7-0.7-0.4-0.5c0.2-0.3 0.3-0.6 0.4-0.9l0.6-0.2v-1l-0.6-0.2zM12.5 14c-0.8 0-1.5-0.7-1.5-1.5s0.7-1.5 1.5-1.5 1.5 0.7 1.5 1.5-0.7 1.5-1.5 1.5z"></path>
</svg>
{
class CrowIDE : CrowWindow
{
- public Command CMDNew, CMDOpen, CMDSave, CMDSaveAs, CMDQuit,
+ public Command CMDNew, CMDOpen, CMDSave, CMDSaveAs, cmdCloseSolution, CMDQuit,
CMDUndo, CMDRedo, CMDCut, CMDCopy, CMDPaste, CMDHelp,
CMDAbout, CMDOptions,
CMDViewGTExp, CMDViewProps, CMDViewProj, CMDViewProjProps, CMDViewErrors, CMDViewSolution, CMDViewEditor, CMDViewProperties,
CMDHelp = new Command(new Action(() => System.Diagnostics.Debug.WriteLine("help"))) { Caption = "Help", Icon = new SvgPicture("#Crow.Coding.ui.icons.question.svg")};
CMDOptions = new Command(new Action(() => openOptionsDialog())) { Caption = "Editor Options", Icon = new SvgPicture("#Crow.Coding.ui.icons.tools.svg")};
+ cmdCloseSolution = new Command(new Action(() => closeSolution())) { Caption = "Close Solution", Icon = new SvgPicture("#Crow.Coding.ui.icons.paste-on-document.svg"), CanExecute = true};
+
CMDViewErrors = new Command(new Action(() => loadDockWindow ("#Crow.Coding.ui.DockWindows.winErrors.crow")))
{ Caption = "Errors pane"};
CMDViewSolution = new Command(new Action(() => loadDockWindow ("#Crow.Coding.ui.DockWindows.winSolution.crow")))
CMDViewToolbox = new Command(new Action(() => loadDockWindow ("#Crow.Coding.ui.DockWindows.winToolbox.crow")))
{ Caption = "Toolbox"};
- CMDViewGTExp = new Command(new Action(() => loadWindow ("#Crow.Coding.ui.GTreeExplorer.crow"))) { Caption = "Graphic Tree Explorer"};
+ CMDViewGTExp = new Command(new Action(() => loadDockWindow ("#Crow.Coding.ui.GTreeExplorer.crow"))) { Caption = "Graphic Tree Explorer"};
CMDViewProps = new Command(new Action(() => loadWindow ("#Crow.Coding.ui.MemberView.crow"))) { Caption = "Properties View"};
CMDCompile = new Command(new Action(() => compileSolution())) { Caption = "Compile"};
CMDViewProj = new Command(new Action(() => loadWindow ("#Crow.Coding.ui.CSProjExplorer.crow"))) { Caption = "Project Explorer"};
void saveFileDialog() {}
void undo() {}
void redo() {}
-
+ void closeSolution (){
+ if (currentSolution != null)
+ currentSolution.CloseSolution ();
+ CurrentSolution = null;
+ }
[STAThread]
static void Main ()
if (currentSolution == value)
return;
currentSolution = value;
- NotifyValueChanged ("CurrentSolution", currentSolution);
+ lock (MainIFace) {
+ NotifyValueChanged ("CurrentSolution", currentSolution);
+ }
}
}
using System.Threading;
using System.Collections.Generic;
using System.Diagnostics;
+using System.IO;
namespace Crow.Coding
{
System.Diagnostics.Debugger.Break ();
return null;
}
+ public override System.IO.Stream GetStreamFromPath (string path)
+ {
+ ProjectFile pi;
+ if (ProjFile.Project.solution.GetProjectFileFromPath (path, out pi)) {
+ return new FileStream (pi.AbsolutePath, FileMode.Open);
+ }
+
+ Console.WriteLine ("File not found: {0}", path);
+ return null;
+ }
public override bool ProcessMouseMove (int x, int y)
{
int deltaX = x - Mouse.X;
LayoutingQueueItem lqi;
while (LayoutingQueue.Count > 0) {
lqi = LayoutingQueue.Dequeue ();
- Console.WriteLine (lqi.ToString ());
+ //Console.WriteLine (lqi.ToString ());
#if DEBUG_LAYOUTING
currentLQI = lqi;
curLQIsTries.Add(currentLQI);
+++ /dev/null
-//
-// EditPane.cs
-//
-// Author:
-// Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using Crow;
-using System.Linq;
-
-namespace Crow.Coding
-{
- public class EditPane : TemplatedGroup
- {
- public EditPane () {}
-
- object selectedItemElement = null;
-
- public override int SelectedIndex {
- get {
- return base.SelectedIndex;
- }
- set {
- base.SelectedIndex = value;
- }
- }
- public object SelectedItemElement {
- get { return selectedItemElement; }
- set {
- if (selectedItemElement == value)
- return;
- selectedItemElement = value;
- NotifyValueChanged ("SelectedItemElement", selectedItemElement);
- }
- }
- }
-}
-
+++ /dev/null
-//
-// Editor.cs
-//
-// Author:
-// Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using System.Threading;
-using System.Xml.Serialization;
-
-namespace Crow.Coding
-{
- public abstract class Editor : ScrollingObject
- {
- #region CTOR
- protected Editor ():base(){
- Thread t = new Thread (backgroundThreadFunc);
- t.IsBackground = true;
- t.Start ();
- }
- #endregion
-
- protected ReaderWriterLockSlim editorMutex = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
- protected ProjectFile projFile = null;
- Exception error = null;
-
- public virtual ProjectFile ProjectNode
- {
- get { return projFile; }
- set
- {
- if (projFile == value)
- return;
-
- if (projFile != null)
- projFile.UnregisterEditor (this);
-
- projFile = value;
-
- if (projFile != null)
- projFile.RegisterEditor (this);
-
- NotifyValueChanged ("ProjectNode", projFile);
- }
- }
- [XmlIgnore]public Exception Error {
- get { return error; }
- set {
- if (error == value)
- return;
- error = value;
- NotifyValueChanged ("Error", error);
- NotifyValueChanged ("HasError", HasError);
- }
- }
- [XmlIgnore]public bool HasError {
- get { return error != null; }
- }
-
- protected abstract void updateEditorFromProjFile ();
- protected abstract void updateProjFileFromEditor ();
- protected abstract bool EditorIsDirty { get; set; }
- protected virtual bool IsReady { get { return true; }}
- protected virtual void updateCheckPostProcess () {}
-
- protected void backgroundThreadFunc () {
- while (true) {
- if (IsReady) {
- if (projFile != null) {
- if (!projFile.RegisteredEditors [this]) {
- projFile.RegisteredEditors [this] = true;
- updateEditorFromProjFile ();
- } else if (EditorIsDirty) {
- EditorIsDirty = false;
- updateProjFileFromEditor ();
- }
- updateCheckPostProcess ();
- }
- }
- Thread.Sleep (50);
- }
- }
- }
-}
-
--- /dev/null
+//
+// CodeTextBuffer.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2017 jp
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Diagnostics;
+using System.Threading;
+
+namespace Crow.Coding
+{
+ /// <summary>
+ /// Code buffer, lines are arranged in a List<string>, new line chars are removed during string.split on '\n...',
+ /// </summary>
+ public class CodeBuffer
+ {
+ public ReaderWriterLockSlim editMutex = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
+
+ //those events are handled in SourceEditor to help keeping sync between textbuffer,parser and editor.
+ //modified lines are marked for reparse
+ #region Events
+ public event EventHandler<CodeBufferEventArgs> LineUpadateEvent;
+ public event EventHandler<CodeBufferEventArgs> LineRemoveEvent;
+ public event EventHandler<CodeBufferEventArgs> LineAdditionEvent;
+ public event EventHandler<CodeBufferEventArgs> FoldingEvent;
+ public event EventHandler BufferCleared;
+ public event EventHandler SelectionChanged;
+ public event EventHandler PositionChanged;
+ #endregion
+
+ string lineBreak = Interface.LineBreak;
+ List<CodeLine> lines = new List<CodeLine>();
+ public int longestLineIdx = 0;
+ public int longestLineCharCount = 0;
+ /// <summary>
+ /// real position in char arrays, tab = 1 char
+ /// </summary>
+ int _currentLine = 0;
+ int _currentCol = 0;
+
+ public int LineCount { get { return lines.Count;}}
+ public int IndexOf (CodeLine cl) {
+ return lines.IndexOf (cl);
+ }
+
+ public CodeLine this[int i]
+ {
+ get { return lines[i]; }
+ set {
+ if (lines [i] == value)
+ return;
+ editMutex.EnterWriteLock ();
+ lines [i] = value;
+ editMutex.ExitWriteLock ();
+ LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i));
+ }
+ }
+
+ public void RemoveAt(int i){
+ editMutex.EnterWriteLock ();
+ lines.RemoveAt (i);
+ editMutex.ExitWriteLock ();
+ LineRemoveEvent.Raise (this, new CodeBufferEventArgs (i));
+ }
+ public void Insert(int i, string item){
+ editMutex.EnterWriteLock ();
+ lines.Insert (i, item);
+ editMutex.ExitWriteLock ();
+ LineAdditionEvent.Raise (this, new CodeBufferEventArgs (i));
+ }
+ public void Add(CodeLine item){
+ editMutex.EnterWriteLock ();
+ lines.Add (item);
+ editMutex.ExitWriteLock ();
+ LineAdditionEvent.Raise (this, new CodeBufferEventArgs (lines.Count - 1));
+ }
+ public void AddRange (string[] items){
+ int start = lines.Count;
+ editMutex.EnterWriteLock ();
+ for (int i = 0; i < items.Length; i++)
+ lines.Add (items [i]);
+ editMutex.ExitWriteLock ();
+ LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length));
+ }
+ public void AddRange (CodeLine[] items){
+ int start = lines.Count;
+ editMutex.EnterWriteLock ();
+ lines.AddRange (items);
+ editMutex.ExitWriteLock ();
+ LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length));
+ }
+ public void Clear () {
+ editMutex.EnterWriteLock ();
+ longestLineCharCount = 0;
+ lines.Clear ();
+ editMutex.ExitWriteLock ();
+ BufferCleared.Raise (this, null);
+ }
+ public void UpdateLine(int i, string newContent){
+ editMutex.EnterWriteLock ();
+ this [i].Content = newContent;
+ editMutex.ExitWriteLock ();
+ LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i));
+ }
+ public void AppenedLine(int i, string newContent){
+ editMutex.EnterWriteLock ();
+ this [i].Content += newContent;
+ editMutex.ExitWriteLock ();
+ LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i));
+ }
+ public void RemoveLeadingTab (int l) {
+ if (this [l] [0] == '\t') {
+ UpdateLine (l, this [l].Content.Substring (1));
+ return;
+ }
+ int i = 0;
+ while (i < Interface.TabSize) {
+ if (this [l] [i] != ' ')
+ break;
+ i++;
+ }
+ if (i > 0)
+ UpdateLine (l, this [l].Content.Substring (i));
+ }
+ public void ToogleFolding (int line) {
+ if (!this [line].IsFoldable)
+ return;
+ editMutex.EnterWriteLock ();
+ this [line].IsFolded = !this [line].IsFolded;
+ editMutex.ExitWriteLock ();
+ FoldingEvent.Raise (this, new CodeBufferEventArgs (line));
+ }
+ public void Load(string rawSource, string lineBrkRegex = @"\r\n|\r|\n|\\\n") {
+ this.Clear();
+
+ if (string.IsNullOrEmpty (rawSource))
+ return;
+
+ AddRange (Regex.Split (rawSource, lineBrkRegex));
+
+ lineBreak = detectLineBreakKind (rawSource);
+ }
+
+ /// <summary>
+ /// Finds the longest visual line as printed on screen with tabulation replaced with n spaces
+ /// </summary>
+ public void FindLongestVisualLine(){
+ longestLineCharCount = 0;
+ editMutex.EnterReadLock ();
+ for (int i = 0; i < this.LineCount; i++) {
+ if (lines[i].PrintableLength > longestLineCharCount) {
+ longestLineCharCount = lines[i].PrintableLength;
+ longestLineIdx = i;
+ }
+ }
+ editMutex.ExitReadLock ();
+ //Debug.WriteLine ("Longest line: {0}->{1}", longestLineIdx, longestLineCharCount);
+ }
+ /// <summary> line break could be '\r' or '\n' or '\r\n' </summary>
+ static string detectLineBreakKind(string buffer){
+ string strLB = "";
+
+ if (string.IsNullOrEmpty(buffer))
+ return Interface.LineBreak;
+ int i = 0;
+ while ( i < buffer.Length) {
+ if (buffer [i] == '\r') {
+ strLB += '\r';
+ i++;
+ }
+ if (i < buffer.Length) {
+ if (buffer [i] == '\r')
+ return "\r";
+ if (buffer[i] == '\n')
+ strLB += '\n';
+ }
+ if (!string.IsNullOrEmpty (strLB))
+ return strLB;
+ i++;
+ }
+ return Interface.LineBreak;
+ }
+ /// <summary>
+ /// return all lines with linebreaks
+ /// </summary>
+ public string FullText{
+ get {
+ if (lines.Count == 0)
+ return "";
+ string tmp = "";
+ editMutex.EnterReadLock ();
+ for (int i = 0; i < lines.Count -1; i++)
+ tmp += lines [i].Content + this.lineBreak;
+ tmp += lines [lines.Count - 1].Content;
+ editMutex.ExitReadLock ();
+ return tmp;
+ }
+ }
+
+ /// <summary>
+ /// unfolded and not in folds line count
+ /// </summary>
+ public int UnfoldedLines {
+ get {
+ int i = 0, vl = 0;
+ editMutex.EnterReadLock ();
+ while (i < LineCount) {
+ if (this [i].IsFolded) {
+ i = GetEndNodeIndex (i);
+ if (i < 0) {
+ Console.WriteLine ("error folding");
+ break;
+ }
+ }
+ i++;
+ vl++;
+ }
+ editMutex.ExitReadLock ();
+ //Debug.WriteLine ("unfolded lines: " + vl);
+ return vl;
+ }
+ }
+
+ /// <summary>
+ /// convert visual position to buffer position
+ /// </summary>
+ Point getBuffPos (Point visualPos) {
+ int i = 0;
+ int buffCol = 0;
+ while (i < visualPos.X) {
+ if (this [visualPos.Y] [buffCol] == '\t')
+ i += Interface.TabSize;
+ else
+ i++;
+ buffCol++;
+ }
+ return new Point (buffCol, visualPos.Y);
+ }
+
+ public int GetEndNodeIndex (int line) {
+ return IndexOf (this [line].SyntacticNode.EndLine);
+ }
+
+ int ConverteTabulatedPosOfCurLine (int column) {
+ int tmp = 0;
+ int i = 0;
+ while (i < lines [_currentLine].Content.Length){
+ if (lines [_currentLine].Content [i] == '\t')
+ tmp += 4;
+ else
+ tmp++;
+ if (tmp > column)
+ break;
+ i++;
+ }
+ return i;
+ }
+
+ public int CurrentTabulatedColumn {
+ get {
+ return lines [_currentLine].Content.Substring (0, _currentCol).
+ Replace ("\t", new String (' ', Interface.TabSize)).Length;
+ }
+ }
+ /// <summary>
+ /// Gets visual position computed from actual buffer position
+ /// </summary>
+// public Point TabulatedPosition {
+// get { return new Point (TabulatedColumn, _currentLine); }
+// }
+ /// <summary>
+ /// set buffer current position from visual position
+ /// </summary>
+// public void SetBufferPos(Point tabulatedPosition) {
+// CurrentPosition = getBuffPos(tabulatedPosition);
+// }
+
+ #region Editing and moving cursor
+ Point selStartPos = -1; //selection start (row,column)
+ Point selEndPos = -1; //selection end (row,column)
+
+ public bool SelectionInProgress { get { return selStartPos >= 0; }}
+ public void SetSelStartPos () {
+ selStartPos = selEndPos = CurrentPosition;
+ SelectionChanged.Raise (this, null);
+ }
+ public void SetSelEndPos () {
+ selEndPos = CurrentPosition;
+ SelectionChanged.Raise (this, null);
+ }
+ public void SetSelectionOnFullLines () {
+ if (!SelectionInProgress)
+ return;
+ Point s = new Point (0, SelectionStart.Y);
+ Point e = new Point (this [SelectionEnd.Y].Length, SelectionEnd.Y);
+ selStartPos = s;
+ selEndPos = e;
+ SelectionChanged.Raise (this, null);
+ }
+ /// <summary>
+ /// Set selection in buffer to -1, empty selection
+ /// </summary>
+ public void ResetSelection () {
+ selStartPos = selEndPos = -1;
+ SelectionChanged.Raise (this, null);
+ }
+
+ public string SelectedText {
+ get {
+ if (SelectionIsEmpty)
+ return "";
+ Point selStart = SelectionStart;
+ Point selEnd = SelectionEnd;
+ if (selStart.Y == selEnd.Y)
+ return this [selStart.Y].Content.Substring (selStart.X, selEnd.X - selStart.X);
+ string tmp = "";
+ tmp = this [selStart.Y].Content.Substring (selStart.X);
+ for (int l = selStart.Y + 1; l < selEnd.Y; l++) {
+ tmp += Interface.LineBreak + this [l].Content;
+ }
+ tmp += Interface.LineBreak + this [selEnd.Y].Content.Substring (0, selEnd.X);
+ return tmp;
+ }
+ }
+ /// <summary>
+ /// ordered selection start and end positions in char units
+ /// </summary>
+ public Point SelectionStart {
+ get { return selEndPos < 0 || selStartPos.Y < selEndPos.Y ? selStartPos :
+ selStartPos.Y > selEndPos.Y ? selEndPos :
+ selStartPos.X < selEndPos.X ? selStartPos : selEndPos; }
+ }
+ public Point SelectionEnd {
+ get { return selEndPos < 0 || selStartPos.Y > selEndPos.Y ? selStartPos :
+ selStartPos.Y < selEndPos.Y ? selEndPos :
+ selStartPos.X > selEndPos.X ? selStartPos : selEndPos; }
+ }
+ public bool SelectionIsEmpty
+ { get { return selEndPos == selStartPos; } }
+ int requestedColumn = -1;
+ /// <summary>
+ /// Current column in buffer coordinate, tabulation = 1 char
+ /// </summary>
+ public int CurrentColumn{
+ get { return _currentCol; }
+ set {
+ if (value == _currentCol)
+ return;
+
+ editMutex.EnterReadLock ();
+
+ if (value < 0)
+ _currentCol = 0;
+ else if (value > lines [_currentLine].Length)
+ _currentCol = lines [_currentLine].Length;
+ else
+ _currentCol = value;
+
+ requestedColumn = CurrentTabulatedColumn;
+
+ editMutex.ExitReadLock ();
+
+ PositionChanged.Raise (this, null);
+ }
+ }
+ /// <summary>
+ /// Current row in buffer coordinate, tabulation = 1 char
+ /// </summary>
+ public int CurrentLine{
+ get { return _currentLine; }
+ set {
+ if (value == _currentLine)
+ return;
+
+ editMutex.EnterReadLock ();
+
+ if (value >= lines.Count)
+ _currentLine = lines.Count-1;
+ else if (value < 0)
+ _currentLine = 0;
+ else
+ _currentLine = value;
+// if (_currentCol < 0)
+// requestedColumn = tabu _currentCol;
+ int tabulatedRequestedCol = ConverteTabulatedPosOfCurLine(requestedColumn);
+ if (requestedColumn > lines [_currentLine].PrintableLength)
+ _currentCol = lines [_currentLine].Length;
+ else
+ //_currentCol = requestedColumn;
+ _currentCol = tabulatedRequestedCol;
+ //Debug.WriteLine ("buff cur line: " + _currentLine);
+
+ editMutex.ExitReadLock();
+
+ PositionChanged.Raise (this, null);
+ }
+ }
+ public CodeLine CurrentCodeLine {
+ get { return this [_currentLine]; }
+ }
+ /// <summary>
+ /// Current position in buffer coordinate, tabulation = 1 char
+ /// </summary>
+ public Point CurrentPosition {
+ get { return new Point(CurrentColumn, CurrentLine); }
+// set {
+// _currentCol = value.X;
+// _currentLine = value.Y;
+// }
+ }
+ /// <summary>
+ /// get char at current position in buffer
+ /// </summary>
+ protected Char CurrentChar { get { return lines [CurrentLine] [CurrentColumn]; } }
+
+ public void GotoWordStart(){
+ if (this[CurrentLine].Length == 0)
+ return;
+ CurrentColumn--;
+ //skip white spaces
+ while (!char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn > 0)
+ CurrentColumn--;
+ while (char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn > 0)
+ CurrentColumn--;
+ if (!char.IsLetterOrDigit (this.CurrentChar))
+ CurrentColumn++;
+ }
+ public void GotoWordEnd(){
+ //skip white spaces
+ if (CurrentColumn >= this [CurrentLine].Length - 1)
+ return;
+ while (!char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn < this [CurrentLine].Length-1)
+ CurrentColumn++;
+ while (char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn < this [CurrentLine].Length-1)
+ CurrentColumn++;
+ if (char.IsLetterOrDigit (this.CurrentChar))
+ CurrentColumn++;
+ }
+ public void DeleteChar()
+ {
+ editMutex.EnterWriteLock ();
+ if (SelectionIsEmpty) {
+ if (CurrentColumn == 0) {
+ if (CurrentLine == 0) {
+ editMutex.ExitWriteLock ();
+ return;
+ }
+ CurrentLine--;
+ CurrentColumn = this [CurrentLine].Length;
+ AppenedLine (CurrentLine, this [CurrentLine + 1].Content);
+ RemoveAt (CurrentLine + 1);
+ editMutex.ExitWriteLock ();
+ return;
+ }
+ CurrentColumn--;
+ UpdateLine (CurrentLine, this [CurrentLine].Content.Remove (CurrentColumn, 1));
+ } else {
+ int linesToRemove = SelectionEnd.Y - SelectionStart.Y + 1;
+ int l = SelectionStart.Y;
+
+ if (linesToRemove > 0) {
+ UpdateLine (l, this [l].Content.Remove (SelectionStart.X, this [l].Length - SelectionStart.X) +
+ this [SelectionEnd.Y].Content.Substring (SelectionEnd.X, this [SelectionEnd.Y].Length - SelectionEnd.X));
+ l++;
+ for (int c = 0; c < linesToRemove - 1; c++)
+ RemoveAt (l);
+ CurrentLine = SelectionStart.Y;
+ CurrentColumn = SelectionStart.X;
+ } else
+ UpdateLine (l, this [l].Content.Remove (SelectionStart.X, SelectionEnd.X - SelectionStart.X));
+ CurrentColumn = SelectionStart.X;
+ ResetSelection ();
+ }
+ editMutex.ExitWriteLock ();
+ }
+ /// <summary>
+ /// Insert new string at caret position, should be sure no line break is inside.
+ /// </summary>
+ /// <param name="str">String.</param>
+ public void Insert(string str)
+ {
+ if (!SelectionIsEmpty)
+ this.DeleteChar ();
+ string[] strLines = Regex.Split (str, "\r\n|\r|\n|" + @"\\n").ToArray();
+ UpdateLine (CurrentLine, this [CurrentLine].Content.Insert (CurrentColumn, strLines[0]));
+ CurrentColumn += strLines[0].Length;
+ for (int i = 1; i < strLines.Length; i++) {
+ InsertLineBreak ();
+ UpdateLine (CurrentLine, this [CurrentLine].Content.Insert (CurrentColumn, strLines[i]));
+ CurrentColumn += strLines[i].Length;
+ }
+ }
+ /// <summary>
+ /// Insert a line break.
+ /// </summary>
+ public void InsertLineBreak()
+ {
+ if (CurrentColumn > 0) {
+ Insert (CurrentLine + 1, this [CurrentLine].Content.Substring (CurrentColumn));
+ UpdateLine (CurrentLine, this [CurrentLine].Content.Substring (0, CurrentColumn));
+ } else
+ Insert(CurrentLine, "");
+
+ CurrentColumn = 0;
+ CurrentLine++;
+ }
+ #endregion
+ }
+}
+
--- /dev/null
+using System;
+
+namespace Crow.Coding
+{
+ public class CodeBufferEventArgs : EventArgs {
+ public int LineStart;
+ public int LineCount;
+
+ public CodeBufferEventArgs(int lineNumber) {
+ LineStart = lineNumber;
+ LineCount = 1;
+ }
+ public CodeBufferEventArgs(int lineStart, int lineCount) {
+ LineStart = lineStart;
+ LineCount = lineCount;
+ }
+ }
+
+}
+
--- /dev/null
+using System;
+using System.Text;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Crow.Coding
+{
+ public class CodeLine
+ {
+ public string Content;
+ public List<Token> Tokens;
+ public int EndingState = 0;
+ public Node SyntacticNode;
+ public ParserException exception;
+
+ public CodeLine (string _content){
+ Content = _content;
+ Tokens = null;
+ exception = null;
+ }
+
+ public char this[int i]
+ {
+ get { return Content[i]; }
+ set {
+ if (Content [i] == value)
+ return;
+ StringBuilder sb = new StringBuilder(Content);
+ sb[i] = value;
+ Content = sb.ToString();
+ Tokens = null;
+ //LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i));
+ }
+ }
+ public bool IsFoldable { get { return SyntacticNode == null ? false :
+ SyntacticNode.EndLine != SyntacticNode.StartLine && SyntacticNode.EndLine != null; } }
+ public int FoldingLevel { get { return IsFoldable ? SyntacticNode.Level : 0; } }
+ public bool IsFolded = false;
+ public bool IsParsed {
+ get { return Tokens != null; }
+ }
+ public string PrintableContent {
+ get {
+ return string.IsNullOrEmpty (Content) ? "" : Content.Replace ("\t", new String (' ', Interface.TabSize));
+ }
+ }
+ public int PrintableLength {
+ get {
+ return PrintableContent.Length;
+ }
+ }
+ public int Length {
+ get {
+ return string.IsNullOrEmpty (Content) ? 0 : Content.Length;
+ }
+ }
+ public int FirstNonBlankTokIndex {
+ get { return Tokens == null ? -1 : Tokens.FindIndex (tk=>tk.Type != BufferParser.TokenType.WhiteSpace); }
+ }
+
+ public void SetLineInError (ParserException ex) {
+ Tokens = null;
+ exception = ex;
+ }
+
+// public static implicit operator string(CodeLine sl) {
+// return sl == null ? "" : sl.Content;
+// }
+ public static implicit operator CodeLine(string s) {
+ return new CodeLine(s);
+ }
+ public static bool operator ==(string s1, CodeLine s2)
+ {
+ return string.Equals (s1, s2.Content);
+ }
+ public static bool operator !=(string s1, CodeLine s2)
+ {
+ return !string.Equals (s1, s2.Content);
+ }
+ }
+}
+
--- /dev/null
+using System;
+using System.Collections.Generic;
+
+namespace Crow.Coding
+{
+ public class Node
+ {
+ public Node Parent;
+ public string Name;
+ public string Type;
+ public CodeLine StartLine;
+ public CodeLine EndLine;
+ public Dictionary<string,string> Attributes = new Dictionary<string, string> ();
+
+ public List<Node> Children = new List<Node>();
+
+ public Node ()
+ {
+ }
+
+ public void AddChild (Node child) {
+ child.Parent = this;
+ Children.Add (child);
+ }
+
+ public int Level {
+ get { return Parent == null ? 1 : Parent.Level + 1; }
+ }
+
+ public override string ToString ()
+ {
+ return string.Format ("Name:{0}, Type:{1}\n\tparent:{2}", Name, Type, Parent);
+ }
+ }
+}
+
--- /dev/null
+//
+// ScrollingTextBox.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Xml.Serialization;
+using System.ComponentModel;
+using System.Collections;
+using Cairo;
+using System.Text;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using System.Linq;
+using System.Diagnostics;
+using System.IO;
+using System.Threading;
+
+namespace Crow.Coding
+{
+ /// <summary>
+ /// Scrolling text box optimized for monospace fonts, for coding
+ /// </summary>
+ public class SourceEditor : Editor
+ {
+ #region CTOR
+ public SourceEditor (): base()
+ {
+ formatting.Add ((int)XMLParser.TokenType.AttributeName, new TextFormatting (Color.Teal, Color.Transparent));
+ formatting.Add ((int)XMLParser.TokenType.ElementName, new TextFormatting (Color.DarkBlue, Color.Transparent));
+ formatting.Add ((int)XMLParser.TokenType.ElementStart, new TextFormatting (Color.Black, Color.Transparent));
+ formatting.Add ((int)XMLParser.TokenType.ElementEnd, new TextFormatting (Color.Black, Color.Transparent));
+ formatting.Add ((int)XMLParser.TokenType.ElementClosing, new TextFormatting (Color.Black, Color.Transparent));
+
+ formatting.Add ((int)XMLParser.TokenType.AttributeValueOpening, new TextFormatting (Color.Carmine, Color.Transparent));
+ formatting.Add ((int)XMLParser.TokenType.AttributeValueClosing, new TextFormatting (Color.Carmine, Color.Transparent));
+ formatting.Add ((int)XMLParser.TokenType.AttributeValue, new TextFormatting (Color.TractorRed, Color.Transparent, false, true));
+ formatting.Add ((int)XMLParser.TokenType.XMLDecl, new TextFormatting (Color.AoEnglish, Color.Transparent));
+
+ formatting.Add ((int)BufferParser.TokenType.BlockComment, new TextFormatting (Color.Gray, Color.Transparent, false, true));
+ formatting.Add ((int)BufferParser.TokenType.LineComment, new TextFormatting (Color.Gray, Color.Transparent, false, true));
+ formatting.Add ((int)BufferParser.TokenType.OperatorOrPunctuation, new TextFormatting (Color.Black, Color.Transparent));
+ //formatting.Add ((int)BufferParser.TokenType.Keyword, new TextFormatting (Color.DarkCyan, Color.Transparent));
+
+ parsing.Add (".crow", "Crow.Coding.XMLParser");
+ parsing.Add (".svg", "Crow.Coding.XMLParser");
+ parsing.Add (".template", "Crow.Coding.XMLParser");
+ parsing.Add (".cs", "Crow.Coding.CSharpParser");
+ parsing.Add (".style", "Crow.Coding.StyleParser");
+
+ buffer = new CodeBuffer ();
+ buffer.LineUpadateEvent += Buffer_LineUpadateEvent;
+ buffer.LineAdditionEvent += Buffer_LineAdditionEvent;;
+ buffer.LineRemoveEvent += Buffer_LineRemoveEvent;
+ buffer.BufferCleared += Buffer_BufferCleared;
+ buffer.SelectionChanged += Buffer_SelectionChanged;
+ buffer.PositionChanged += Buffer_PositionChanged;
+ buffer.FoldingEvent += Buffer_FoldingEvent;
+ buffer.Add (new CodeLine(""));
+ }
+ #endregion
+
+ string oldSource = "";
+ //save requested position on error, and try it on next move
+ int requestedLine = 0, requestedCol = 0;
+ volatile bool isDirty = false;
+
+ const int leftMarginGap = 3;//gap between items in margin and text
+ const int foldSize = 9;//folding rectangles size
+ const int foldHSpace = 4;//folding level tabulation x
+ int foldMargin { get { return parser == null ? 0 : parser.SyntacticTreeMaxDepth * foldHSpace; }}//folding margin size
+
+ #region private and protected fields
+ bool foldingEnabled = true;
+ int leftMargin = 0; //margin used to display line numbers, folding errors,etc...
+ int visibleLines = 1;
+ int visibleColumns = 1;
+ int firstPrintedLine = -1;
+ int printedCurrentLine = 0;//Index of the currentline in the PrintedLines array
+
+ CodeBuffer buffer;
+ BufferParser parser;
+ List<CodeLine> PrintedLines;//list of lines visible in the Editor depending on scrolling and folding
+
+ Dictionary<int, TextFormatting> formatting = new Dictionary<int, TextFormatting>();
+ Dictionary<string, string> parsing = new Dictionary<string, string>();
+
+ Color selBackground;
+ Color selForeground;
+ int selStartCol;
+ int selEndCol;
+
+ protected Rectangle rText;
+ protected FontExtents fe;
+ protected TextExtents te;
+
+ Point mouseLocalPos;
+ bool doubleClicked = false;
+ #endregion
+
+ void measureLeftMargin () {
+ leftMargin = 0;
+ if (PrintLineNumbers)
+ leftMargin += (int)Math.Ceiling((double)buffer.LineCount.ToString().Length * fe.MaxXAdvance) +6;
+ if (foldingEnabled)
+ leftMargin += foldMargin;
+ if (leftMargin > 0)
+ leftMargin += leftMarginGap;
+ updateVisibleColumns ();
+ }
+ void findLongestLineAndUpdateMaxScrollX() {
+ buffer.FindLongestVisualLine ();
+ updateMaxScrollX ();
+// Debug.WriteLine ("SourceEditor: Find Longest line and update maxscrollx: {0} visible cols:{1}", MaxScrollX, visibleColumns);
+ }
+ /// <summary>
+ /// Updates visible line in widget, adapt max scroll y and updatePrintedLines
+ /// </summary>
+ void updateVisibleLines(){
+ visibleLines = (int)Math.Floor ((double)ClientRectangle.Height / (fe.Ascent+fe.Descent));
+ NotifyValueChanged ("VisibleLines", visibleLines);
+ updateMaxScrollY ();
+ updatePrintedLines ();
+ RegisterForGraphicUpdate ();
+// System.Diagnostics.Debug.WriteLine ("update visible lines: " + visibleLines);
+// System.Diagnostics.Debug.WriteLine ("update MaxScrollY: " + MaxScrollY);
+ }
+ void updateVisibleColumns(){
+ visibleColumns = (int)Math.Floor ((double)(ClientRectangle.Width - leftMargin)/ fe.MaxXAdvance);
+ NotifyValueChanged ("VisibleColumns", visibleColumns);
+ updateMaxScrollX ();
+// System.Diagnostics.Debug.WriteLine ("update visible columns: {0} leftMargin:{1}",visibleColumns, leftMargin);
+// System.Diagnostics.Debug.WriteLine ("update MaxScrollX: " + MaxScrollX);
+ }
+ void updateMaxScrollX () {
+ MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns);
+ if (buffer.longestLineCharCount > 0)
+ NotifyValueChanged ("ChildWidthRatio", Slot.Width * visibleColumns / buffer.longestLineCharCount);
+ }
+ void updateMaxScrollY () {
+ if (parser == null || !foldingEnabled) {
+ MaxScrollY = Math.Max (0, buffer.LineCount - visibleLines);
+ if (buffer.UnfoldedLines > 0)
+ NotifyValueChanged ("ChildHeightRatio", Slot.Height * visibleLines / buffer.UnfoldedLines);
+ } else {
+ MaxScrollY = Math.Max (0, buffer.UnfoldedLines - visibleLines);
+ if (buffer.UnfoldedLines > 0)
+ NotifyValueChanged ("ChildHeightRatio", Slot.Height * visibleLines / buffer.UnfoldedLines);
+ }
+ }
+ void updatePrintedLines () {
+ buffer.editMutex.EnterReadLock ();
+ editorMutex.EnterWriteLock ();
+
+ PrintedLines = new List<CodeLine> ();
+ int curL = 0;
+ int i = 0;
+
+ while (curL < buffer.LineCount && i < ScrollY) {
+ if (buffer [curL].IsFolded)
+ curL = buffer.GetEndNodeIndex (curL);
+ curL++;
+ i++;
+ }
+
+ firstPrintedLine = curL;
+ i = 0;
+ while (i < visibleLines && curL < buffer.LineCount) {
+ PrintedLines.Add (buffer [curL]);
+
+ if (buffer [curL].IsFolded)
+ curL = buffer.GetEndNodeIndex (curL);
+
+ curL++;
+ i++;
+ }
+
+ buffer.editMutex.ExitReadLock ();
+ editorMutex.ExitWriteLock ();
+ }
+ void updateOnScreenCurLineFromBuffCurLine(){
+ printedCurrentLine = PrintedLines.IndexOf (buffer.CurrentCodeLine);
+ }
+ void toogleFolding (int line) {
+ if (parser == null || !foldingEnabled)
+ return;
+ buffer.ToogleFolding (line);
+ }
+
+ #region Editor overrides
+ protected override void updateEditorFromProjFile ()
+ {
+ buffer.editMutex.EnterWriteLock ();
+ loadSource ();
+ buffer.editMutex.ExitWriteLock ();
+
+ isDirty = false;
+ oldSource = projFile.Source;
+ CurrentLine = requestedLine;
+ CurrentColumn = requestedCol;
+ projFile.RegisteredEditors [this] = true;
+ }
+ protected override void updateProjFileFromEditor ()
+ {
+ buffer.editMutex.EnterWriteLock ();
+ string newsrc = buffer.FullText;
+ buffer.editMutex.ExitWriteLock ();
+ projFile.UpdateSource (this, newsrc);
+ }
+ protected override bool EditorIsDirty {
+ get { return isDirty; }
+ set { isDirty = value; }
+ }
+ protected override bool IsReady {
+ get { return buffer != null; }
+ }
+ #endregion
+
+ #region Buffer events handlers
+ void Buffer_BufferCleared (object sender, EventArgs e)
+ {
+ editorMutex.EnterWriteLock ();
+
+ buffer.longestLineCharCount = 0;
+ buffer.longestLineIdx = 0;
+ measureLeftMargin ();
+ MaxScrollX = MaxScrollY = 0;
+ PrintedLines = null;
+ RegisterForGraphicUpdate ();
+ notifyPositionChanged ();
+ isDirty = true;
+
+ editorMutex.ExitWriteLock ();
+ }
+ void Buffer_LineAdditionEvent (object sender, CodeBufferEventArgs e)
+ {
+ for (int i = 0; i < e.LineCount; i++) {
+ int lptr = e.LineStart + i;
+ int charCount = buffer[lptr].PrintableLength;
+ if (charCount > buffer.longestLineCharCount) {
+ buffer.longestLineIdx = lptr;
+ buffer.longestLineCharCount = charCount;
+ }else if (lptr <= buffer.longestLineIdx)
+ buffer.longestLineIdx++;
+ if (parser == null)
+ continue;
+ parser.TryParseBufferLine (e.LineStart + i);
+ }
+
+ if (parser != null)
+ parser.reparseSource ();
+
+ measureLeftMargin ();
+
+ updatePrintedLines ();
+ updateMaxScrollY ();
+ RegisterForGraphicUpdate ();
+ notifyPositionChanged ();
+ isDirty = true;
+ }
+ void Buffer_LineRemoveEvent (object sender, CodeBufferEventArgs e)
+ {
+ bool trigFindLongestLine = false;
+ for (int i = 0; i < e.LineCount; i++) {
+ int lptr = e.LineStart + i;
+ if (lptr <= buffer.longestLineIdx)
+ trigFindLongestLine = true;
+ }
+ if (trigFindLongestLine)
+ findLongestLineAndUpdateMaxScrollX ();
+
+ measureLeftMargin ();
+ updatePrintedLines ();
+ updateMaxScrollY ();
+ RegisterForGraphicUpdate ();
+ notifyPositionChanged ();
+ isDirty = true;
+ }
+ void Buffer_LineUpadateEvent (object sender, CodeBufferEventArgs e)
+ {
+ bool trigFindLongestLine = false;
+ for (int i = 0; i < e.LineCount; i++) {
+
+ int lptr = e.LineStart + i;
+ if (lptr == buffer.longestLineIdx)
+ trigFindLongestLine = true;
+ else if (buffer[lptr].PrintableLength > buffer.longestLineCharCount) {
+ buffer.longestLineCharCount = buffer[lptr].PrintableLength;
+ buffer.longestLineIdx = lptr;
+ }
+ }
+ if (trigFindLongestLine)
+ findLongestLineAndUpdateMaxScrollX ();
+
+ RegisterForGraphicUpdate ();
+ notifyPositionChanged ();
+ isDirty = true;
+ }
+ void Buffer_PositionChanged (object sender, EventArgs e)
+ {
+ Console.WriteLine ("Position changes: ({0},{1})", buffer.CurrentLine, buffer.CurrentColumn);
+ int cc = buffer.CurrentTabulatedColumn;
+
+ if (cc > visibleColumns + ScrollX) {
+ ScrollX = cc - visibleColumns;
+ } else if (cc < ScrollX)
+ ScrollX = cc;
+
+ RegisterForGraphicUpdate ();
+ updateOnScreenCurLineFromBuffCurLine ();
+ notifyPositionChanged ();
+ }
+
+ void Buffer_SelectionChanged (object sender, EventArgs e)
+ {
+ RegisterForGraphicUpdate ();
+ }
+ void Buffer_FoldingEvent (object sender, CodeBufferEventArgs e)
+ {
+ updatePrintedLines ();
+ updateOnScreenCurLineFromBuffCurLine ();
+ updateMaxScrollY ();
+ RegisterForGraphicUpdate ();
+ }
+ #endregion
+
+ void notifyPositionChanged (){
+ try {
+ NotifyValueChanged ("CurrentLine", buffer.CurrentLine+1);
+ NotifyValueChanged ("CurrentColumn", buffer.CurrentColumn+1);
+ NotifyValueChanged ("CurrentLineHasError", CurrentLineHasError);
+ NotifyValueChanged ("CurrentLineError", CurrentLineError);
+ } catch (Exception ex) {
+ Console.WriteLine (ex.ToString ());
+ }
+ }
+
+ #region Public Crow Properties
+ public int CurrentLine{
+ get { return buffer == null ? 0 : buffer.CurrentLine+1; }
+ set {
+ try {
+ int l = value - 1;
+ if (l == buffer.CurrentLine)
+ return;
+ buffer.CurrentLine = l;
+ if (buffer [l].IsFolded)
+ buffer.ToogleFolding (l);
+ } catch (Exception ex) {
+ requestedLine = value - 1;
+ Console.WriteLine ("Error cur column: " + ex.ToString ());
+ }
+ }
+ }
+ public int CurrentColumn{
+ get { return buffer == null ? 0 : buffer.CurrentColumn+1; }
+ set {
+ try {
+ if (value - 1 == buffer.CurrentColumn)
+ return;
+ buffer.CurrentColumn = value - 1;
+ } catch (Exception ex) {
+ requestedCol = value - 1;
+ Console.WriteLine ("Error cur column: " + ex.ToString ());
+ }
+ }
+ }
+ public bool PrintLineNumbers
+ {
+ get { return Configuration.Global.Get<bool> ("PrintLineNumbers"); }
+ set {
+ if (PrintLineNumbers == value)
+ return;
+ Configuration.Global.Set ("PrintLineNumbers", value);
+ NotifyValueChanged ("PrintLineNumbers", PrintLineNumbers);
+ measureLeftMargin ();
+ RegisterForGraphicUpdate ();
+ }
+ }
+ [DefaultValue("BlueGray")]
+ public virtual Color SelectionBackground {
+ get { return selBackground; }
+ set {
+ if (value == selBackground)
+ return;
+ selBackground = value;
+ NotifyValueChanged ("SelectionBackground", selBackground);
+ RegisterForRedraw ();
+ }
+ }
+ [DefaultValue("White")]
+ public virtual Color SelectionForeground {
+ get { return selForeground; }
+ set {
+ if (value == selForeground)
+ return;
+ selForeground = value;
+ NotifyValueChanged ("SelectionForeground", selForeground);
+ RegisterForRedraw ();
+ }
+ }
+ public override int ScrollY {
+ get {
+ return base.ScrollY;
+ }
+ set {
+ if (value == base.ScrollY)
+ return;
+ base.ScrollY = value;
+ updatePrintedLines ();
+ updateOnScreenCurLineFromBuffCurLine ();
+ RegisterForGraphicUpdate ();
+ }
+ }
+ public ParserException CurrentLineError {
+ get { return buffer?.CurrentCodeLine?.exception; }
+ }
+ public bool CurrentLineHasError {
+ get { return buffer == null ? false : buffer.CurrentCodeLine == null ? false :
+ buffer.CurrentCodeLine.exception != null; }
+ }
+ public override ProjectFile ProjectNode {
+ get {
+ return base.ProjectNode;
+ }
+ set {
+ base.ProjectNode = value;
+ if (projFile != null)
+ parser = getParserFromExt (System.IO.Path.GetExtension (projFile.Extension));
+ }
+ }
+ #endregion
+
+ BufferParser getParserFromExt (string extension) {
+ if (string.IsNullOrEmpty(extension))
+ return null;
+ if (!parsing.ContainsKey(extension))
+ return null;
+ Type parserType = Type.GetType (parsing [extension]);
+ if (parserType == null)
+ return null;
+ return (BufferParser)Activator.CreateInstance (parserType, buffer );
+ }
+ void loadSource () {
+
+ try {
+
+ if (parser == null)
+ buffer.Load (projFile.Source);
+ else//parser may have special linebrk rules
+ buffer.Load (projFile.Source, parser.LineBrkRegex);
+
+ } catch (Exception ex) {
+ Debug.WriteLine (ex.ToString ());
+ }
+
+ projFile.RegisteredEditors [this] = true;
+
+ updateMaxScrollY ();
+ MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns);
+ updatePrintedLines ();
+
+ RegisterForGraphicUpdate ();
+ }
+
+ /// <summary>
+ /// Current editor line, when set, update buffer.CurrentLine
+ /// </summary>
+ int PrintedCurrentLine {
+ get { return printedCurrentLine;}
+ set {
+ if (value < 0) {
+ ScrollY += value;
+ printedCurrentLine = 0;
+ } else if (PrintedLines.Count < visibleLines && value >= PrintedLines.Count) {
+ printedCurrentLine = PrintedLines.Count - 1;
+ }else if (value >= visibleLines) {
+ ScrollY += value - visibleLines + 1;
+ printedCurrentLine = visibleLines - 1;
+ }else
+ printedCurrentLine = value;
+ //Debug.WriteLine ("printed current line:" + printedCurrentLine.ToString ());
+ //update position in buffer
+ buffer.CurrentLine = buffer.IndexOf (PrintedLines[printedCurrentLine]);
+ }
+ }
+ int getTabulatedColumn (int col, int line) {
+ return buffer [line].Content.Substring (0, col).Replace ("\t", new String (' ', Interface.TabSize)).Length;
+ }
+ int getTabulatedColumn (Point pos) {
+ return getTabulatedColumn (pos.X,pos.Y);
+ }
+ /// <summary>
+ /// Moves cursor one char to the left, move up if cursor reaches start of line
+ /// </summary>
+ /// <returns><c>true</c> if move succeed</returns>
+ public bool MoveLeft(){
+ if (buffer.CurrentColumn == 0) {
+ if (printedCurrentLine == 0)
+ return false;
+ PrintedCurrentLine--;
+ buffer.CurrentColumn = int.MaxValue;
+ } else
+ buffer.CurrentColumn--;
+ return true;
+ }
+ /// <summary>
+ /// Moves cursor one char to the right, move down if cursor reaches end of line
+ /// </summary>
+ /// <returns><c>true</c> if move succeed</returns>
+ public bool MoveRight(){
+ if (buffer.CurrentColumn >= buffer.CurrentCodeLine.Length) {
+ if (PrintedCurrentLine == buffer.UnfoldedLines - 1)
+ return false;
+ buffer.CurrentColumn = 0;
+ PrintedCurrentLine++;
+ } else
+ buffer.CurrentColumn++;
+ return true;
+ }
+
+ #region Drawing
+ void drawLine(Context gr, Rectangle cb, int i) {
+ CodeLine cl = PrintedLines[i];
+ int lineIndex = buffer.IndexOf(cl);
+
+ double y = cb.Y + (fe.Ascent+fe.Descent) * i, x = cb.X;
+
+ //Draw line numbering
+ Color mgFg = Color.Gray;
+ Color mgBg = Color.White;
+ if (PrintLineNumbers){
+ Rectangle mgR = new Rectangle ((int)x, (int)y, leftMargin - leftMarginGap, (int)Math.Ceiling((fe.Ascent+fe.Descent)));
+ if (cl.exception != null) {
+ mgBg = Color.Red;
+ if (buffer.CurrentLine == lineIndex)
+ mgFg = Color.White;
+ else
+ mgFg = Color.LightGray;
+ }else if (buffer.CurrentLine == lineIndex) {
+ mgFg = Color.Black;
+ mgBg = Color.DarkGray;
+ }
+ string strLN = (lineIndex+1).ToString ();
+ gr.SetSourceColor (mgBg);
+ gr.Rectangle (mgR);
+ gr.Fill();
+ gr.SetSourceColor (mgFg);
+
+ gr.MoveTo (cb.X + (int)(gr.TextExtents (buffer.LineCount.ToString()).Width - gr.TextExtents (strLN).Width), y + fe.Ascent);
+ gr.ShowText (strLN);
+ gr.Fill ();
+ }
+
+
+
+ //draw folding
+ if (foldingEnabled){
+
+ Rectangle rFld = new Rectangle (cb.X + leftMargin - leftMarginGap - foldMargin,
+ (int)(y + (fe.Ascent + fe.Descent) / 2.0 - foldSize / 2.0), foldSize, foldSize);
+
+ gr.SetSourceColor (Color.Black);
+ gr.LineWidth = 1.0;
+
+ int level = 0;
+ bool closingNode = false;
+
+ if (currentNode != null) {
+ if (cl == currentNode.EndLine) {
+ currentNode = currentNode.Parent;
+ closingNode = true;
+ }
+ if (currentNode != null)
+ level = currentNode.Level - 1;
+ }
+
+ for (int l = 0; l < level; l++) {
+ gr.MoveTo (rFld.Center.X + 0.5, y);
+ gr.LineTo (rFld.Center.X + 0.5, y + fe.Ascent + fe.Descent);
+ rFld.Left += foldHSpace;
+ }
+ if (closingNode) {
+ gr.MoveTo (rFld.Center.X + 0.5, y);
+ gr.LineTo (rFld.Center.X + 0.5, y + fe.Ascent / 2 + 0.5);
+ gr.LineTo (rFld.Center.X + 0.5 + foldSize / 2, y + fe.Ascent / 2 + 0.5);
+ closingNode = false;
+ }
+ gr.SetDash (new double[]{ 1.5 },0.0);
+ gr.SetSourceColor (Color.Gray);
+ gr.Stroke ();
+ gr.SetDash (new double[]{}, 0.0);
+
+ if (cl.IsFoldable) {
+ gr.Rectangle (rFld);
+ gr.SetSourceColor (Color.White);
+ gr.Fill();
+ gr.SetSourceColor (Color.Black);
+ gr.Rectangle (rFld, 1.0);
+ if (cl.IsFolded) {
+ gr.MoveTo (rFld.Center.X + 0.5, rFld.Y + 2);
+ gr.LineTo (rFld.Center.X + 0.5, rFld.Bottom - 2);
+ }else
+ currentNode = cl.SyntacticNode;
+
+ gr.MoveTo (rFld.Left + 2, rFld.Center.Y + 0.5);
+ gr.LineTo (rFld.Right - 2, rFld.Center.Y + 0.5);
+ gr.Stroke ();
+ }
+ }
+
+ gr.SetSourceColor (Foreground);
+ x += leftMargin;
+
+ if (cl.Tokens == null)
+ drawRawCodeLine (gr, x, y, i, lineIndex);
+ else
+ drawParsedCodeLine (gr, x, y, i, lineIndex);
+ }
+ Node currentNode = null;
+// void drawParsed(Context gr){
+// if (PrintedLines == null)
+// return;
+//
+// gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
+// gr.SetFontSize (Font.Size);
+// gr.FontOptions = Interface.FontRenderingOptions;
+// gr.Antialias = Interface.Antialias;
+//
+// Rectangle cb = ClientRectangle;
+// gr.Save ();
+// CairoHelpers.CairoRectangle (gr, cb, CornerRadius);
+// gr.Clip ();
+//
+// bool selectionInProgress = false;
+//
+// Foreground.SetAsSource (gr);
+//
+// #region draw text cursor
+// if (SelBegin != SelRelease)
+// selectionInProgress = true;
+// else if (HasFocus){
+// gr.LineWidth = 1.0;
+// double cursorX = + leftMargin + cb.X + (CurrentColumn - ScrollX) * fe.MaxXAdvance;
+// gr.MoveTo (0.5 + cursorX, cb.Y + printedCurrentLine * (fe.Ascent+fe.Descent));
+// gr.LineTo (0.5 + cursorX, cb.Y + (printedCurrentLine + 1) * (fe.Ascent+fe.Descent));
+// gr.Stroke();
+// }
+// #endregion
+//
+// for (int i = 0; i < PrintedLines.Count; i++)
+// drawTokenLine (gr, i, selectionInProgress, cb);
+//
+// gr.Restore ();
+// }
+ void drawRawCodeLine(Context gr, double x, double y, int i, int lineIndex) {
+ string lstr = buffer[lineIndex].PrintableContent;
+ if (ScrollX < lstr.Length)
+ lstr = lstr.Substring (ScrollX);
+ else
+ lstr = "";
+
+ gr.MoveTo (x, y + fe.Ascent);
+ gr.ShowText (lstr);
+ gr.Fill ();
+
+ if (!buffer.SelectionIsEmpty && lineIndex >= buffer.SelectionStart.Y && lineIndex <= buffer.SelectionEnd.Y) {
+ double rLineX = x,
+ rLineY = y,
+ rLineW = lstr.Length * fe.MaxXAdvance;
+
+ //System.Diagnostics.Debug.WriteLine ("sel start: " + buffer.SelectionStart + " sel end: " + buffer.SelectionEnd);
+ if (lineIndex == buffer.SelectionStart.Y) {
+ rLineX += (selStartCol - ScrollX) * fe.MaxXAdvance;
+ rLineW -= selStartCol * fe.MaxXAdvance;
+ }
+ if (lineIndex == buffer.SelectionEnd.Y)
+ rLineW -= (lstr.Length - selEndCol) * fe.MaxXAdvance;
+
+ gr.Save ();
+ gr.Operator = Operator.Source;
+ gr.Rectangle (rLineX, rLineY, rLineW, (fe.Ascent+fe.Descent));
+ gr.SetSourceColor (SelectionBackground);
+ gr.FillPreserve ();
+ gr.Clip ();
+ gr.Operator = Operator.Over;
+ gr.SetSourceColor (SelectionForeground);
+ gr.MoveTo (x, y + fe.Ascent);
+ gr.ShowText (lstr);
+ gr.Fill ();
+ gr.Restore ();
+ }
+ }
+ void drawParsedCodeLine (Context gr, double x, double y, int i, int lineIndex) {
+ int lPtr = 0;
+ CodeLine cl = PrintedLines[i];
+
+ for (int t = 0; t < cl.Tokens.Count; t++) {
+ string lstr = cl.Tokens [t].PrintableContent;
+ if (lPtr < ScrollX) {
+ if (lPtr - ScrollX + lstr.Length <= 0) {
+ lPtr += lstr.Length;
+ continue;
+ }
+ lstr = lstr.Substring (ScrollX - lPtr);
+ lPtr += ScrollX - lPtr;
+ }
+ Color bg = this.Background;
+ Color fg = this.Foreground;
+ Color selbg = this.SelectionBackground;
+ Color selfg = this.SelectionForeground;
+ FontSlant fts = FontSlant.Normal;
+ FontWeight ftw = FontWeight.Normal;
+
+ if (formatting.ContainsKey ((int)cl.Tokens [t].Type)) {
+ TextFormatting tf = formatting [(int)cl.Tokens [t].Type];
+ bg = tf.Background;
+ fg = tf.Foreground;
+ if (tf.Bold)
+ ftw = FontWeight.Bold;
+ if (tf.Italic)
+ fts = FontSlant.Italic;
+ }
+
+ gr.SelectFontFace (Font.Name, fts, ftw);
+ gr.SetSourceColor (fg);
+
+ gr.MoveTo (x, y + fe.Ascent);
+ gr.ShowText (lstr);
+ gr.Fill ();
+
+ if (buffer.SelectionInProgress && lineIndex >= buffer.SelectionStart.Y && lineIndex <= buffer.SelectionEnd.Y &&
+ !(lineIndex == buffer.SelectionStart.Y && lPtr + lstr.Length <= selStartCol) &&
+ !(lineIndex == buffer.SelectionEnd.Y && selEndCol <= lPtr)) {
+
+ double rLineX = x,
+ rLineY = y,
+ rLineW = lstr.Length * fe.MaxXAdvance;
+ double startAdjust = 0.0;
+
+ if ((lineIndex == buffer.SelectionStart.Y) && (selStartCol < lPtr + lstr.Length) && (selStartCol > lPtr))
+ startAdjust = (selStartCol - lPtr) * fe.MaxXAdvance;
+ rLineX += startAdjust;
+ if ((lineIndex == buffer.SelectionEnd.Y) && (selEndCol < lPtr + lstr.Length))
+ rLineW = (selEndCol - lPtr) * fe.MaxXAdvance;
+ rLineW -= startAdjust;
+
+ gr.Save ();
+ gr.Operator = Operator.Source;
+ gr.Rectangle (rLineX, rLineY, rLineW, (fe.Ascent+fe.Descent));
+ gr.SetSourceColor (selbg);
+ gr.FillPreserve ();
+ gr.Clip ();
+ gr.Operator = Operator.Over;
+ gr.SetSourceColor (selfg);
+ gr.MoveTo (x, y + fe.Ascent);
+ gr.ShowText (lstr);
+ gr.Fill ();
+ gr.Restore ();
+ }
+ x += (int)lstr.Length * fe.MaxXAdvance;
+ lPtr += lstr.Length;
+ }
+ }
+
+ #endregion
+
+ #region GraphicObject overrides
+ public override Font Font {
+ get { return base.Font; }
+ set {
+ base.Font = value;
+
+ using (ImageSurface img = new ImageSurface (Format.Argb32, 1, 1)) {
+ using (Context gr = new Context (img)) {
+ gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
+ gr.SetFontSize (Font.Size);
+
+ fe = gr.FontExtents;
+ }
+ }
+ MaxScrollY = 0;
+ RegisterForGraphicUpdate ();
+ }
+ }
+ protected override int measureRawSize(LayoutingType lt)
+ {
+ if (lt == LayoutingType.Height)
+ return (int)Math.Ceiling((fe.Ascent+fe.Descent) * buffer.LineCount) + Margin * 2;
+
+ return (int)(fe.MaxXAdvance * buffer.longestLineCharCount) + Margin * 2 + leftMargin;
+ }
+ public override void OnLayoutChanges (LayoutingType layoutType)
+ {
+ base.OnLayoutChanges (layoutType);
+
+ if (layoutType == LayoutingType.Height)
+ updateVisibleLines ();
+ else if (layoutType == LayoutingType.Width)
+ updateVisibleColumns ();
+ }
+
+ protected override void onDraw (Context gr)
+ {
+ base.onDraw (gr);
+
+ gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
+ gr.SetFontSize (Font.Size);
+ gr.FontOptions = Interface.FontRenderingOptions;
+ gr.Antialias = Interface.Antialias;
+
+ Rectangle cb = ClientRectangle;
+
+ Foreground.SetAsSource (gr);
+
+ buffer.editMutex.EnterReadLock ();
+ editorMutex.EnterReadLock ();
+
+ #region draw text cursor
+ if (buffer.SelectionInProgress){
+ selStartCol = getTabulatedColumn (buffer.SelectionStart);
+ selEndCol = getTabulatedColumn (buffer.SelectionEnd);
+ }else if (HasFocus && printedCurrentLine >= 0){
+ gr.LineWidth = 1.0;
+ double cursorX = cb.X + (getTabulatedColumn(buffer.CurrentPosition) - ScrollX) * fe.MaxXAdvance + leftMargin;
+ gr.MoveTo (0.5 + cursorX, cb.Y + (printedCurrentLine) * (fe.Ascent+fe.Descent));
+ gr.LineTo (0.5 + cursorX, cb.Y + (printedCurrentLine + 1) * (fe.Ascent+fe.Descent));
+ gr.Stroke();
+ }
+ #endregion
+
+ if (PrintedLines?.Count > 0) {
+ int unfoldedLines = buffer.UnfoldedLines;
+ currentNode = null;
+ CodeLine cl = PrintedLines[0];
+ int idx0 = buffer.IndexOf(cl);
+ int li = idx0-1;
+ while (li >= 0) {
+ if (buffer [li].IsFoldable && !buffer [li].IsFolded) {
+ if (buffer.IndexOf(buffer [li].SyntacticNode.EndLine) > idx0){
+ currentNode = buffer [li].SyntacticNode;
+ break;
+ }
+ }
+ li--;
+ }
+
+ for (int i = 0; i < visibleLines; i++) {
+ if (i + ScrollY >= unfoldedLines)//TODO:need optimize
+ break;
+ drawLine (gr, cb, i);
+ }
+ }
+
+ editorMutex.ExitReadLock ();
+
+ buffer.editMutex.ExitReadLock ();
+
+ }
+ #endregion
+
+ #region Mouse handling
+
+ int hoverLine = -1;
+ public int HoverLine {
+ get { return hoverLine; }
+ set {
+ if (hoverLine == value)
+ return;
+ hoverLine = value;
+ NotifyValueChanged ("HoverLine", hoverLine);
+ }
+ }
+ void updateHoverLine () {
+ int hvl = (int)Math.Max (0, Math.Floor (mouseLocalPos.Y / (fe.Ascent+fe.Descent)));
+ hvl = Math.Min (PrintedLines.Count, hvl);
+ HoverLine = buffer.IndexOf (PrintedLines[hvl]);
+ }
+ void updateCurrentPosFromMouseLocalPos(){
+ PrintedCurrentLine = (int)Math.Max (0, Math.Floor (mouseLocalPos.Y / (fe.Ascent+fe.Descent)));
+ int curVisualCol = ScrollX + (int)Math.Round ((mouseLocalPos.X - leftMargin) / fe.MaxXAdvance);
+
+ int i = 0;
+ int buffCol = 0;
+ while (i < curVisualCol && buffCol < buffer.CurrentCodeLine.Length) {
+ if (buffer.CurrentCodeLine[buffCol] == '\t')
+ i += Interface.TabSize;
+ else
+ i++;
+ buffCol++;
+ }
+ buffer.CurrentColumn = buffCol;
+ }
+ public override void onMouseEnter (object sender, MouseMoveEventArgs e)
+ {
+ base.onMouseEnter (sender, e);
+ if (e.X - ScreenCoordinates(Slot).X < leftMargin + ClientRectangle.X)
+ IFace.MouseCursor = XCursor.Default;
+ else
+ IFace.MouseCursor = XCursor.Text;
+ }
+ public override void onMouseLeave (object sender, MouseMoveEventArgs e)
+ {
+ base.onMouseLeave (sender, e);
+ IFace.MouseCursor = XCursor.Default;
+ }
+ public override void onMouseMove (object sender, MouseMoveEventArgs e)
+ {
+ base.onMouseMove (sender, e);
+
+ mouseLocalPos = e.Position - ScreenCoordinates(Slot).TopLeft - ClientRectangle.TopLeft;
+
+ updateHoverLine ();
+
+ if (!e.Mouse.IsButtonDown (MouseButton.Left)) {
+ if (mouseLocalPos.X < leftMargin)
+ IFace.MouseCursor = XCursor.Default;
+ else
+ IFace.MouseCursor = XCursor.Text;
+ return;
+ }
+
+ if (!HasFocus || !buffer.SelectionInProgress)
+ return;
+
+ //mouse is down
+ updateCurrentPosFromMouseLocalPos();
+ buffer.SetSelEndPos ();
+ }
+ public override void onMouseDown (object sender, MouseButtonEventArgs e)
+ {
+ if (!this.Focusable)
+ return;
+
+ if (mouseLocalPos.X >= leftMargin)
+ base.onMouseDown (sender, e);
+
+ if (doubleClicked) {
+ doubleClicked = false;
+ return;
+ }
+
+ if (mouseLocalPos.X < leftMargin) {
+ toogleFolding (buffer.IndexOf (PrintedLines [(int)Math.Max (0, Math.Floor (mouseLocalPos.Y / (fe.Ascent+fe.Descent)))]));
+ return;
+ }
+
+ updateCurrentPosFromMouseLocalPos ();
+ buffer.SetSelStartPos ();
+ }
+ public override void onMouseUp (object sender, MouseButtonEventArgs e)
+ {
+ base.onMouseUp (sender, e);
+
+ if (buffer.SelectionIsEmpty)
+ buffer.ResetSelection ();
+ }
+
+ public override void onMouseDoubleClick (object sender, MouseButtonEventArgs e)
+ {
+ doubleClicked = true;
+ base.onMouseDoubleClick (sender, e);
+
+ buffer.GotoWordStart ();
+ buffer.SetSelStartPos ();
+ buffer.GotoWordEnd ();
+ buffer.SetSelEndPos ();
+ }
+
+ public override void onMouseWheel (object sender, MouseWheelEventArgs e)
+ {
+ base.onMouseWheel (sender, e);
+ }
+ #endregion
+
+ #region Keyboard handling
+ public override void onKeyDown (object sender, KeyboardKeyEventArgs e)
+ {
+ //base.onKeyDown (sender, e);
+
+ Key key = e.Key;
+
+ if (e.Control) {
+ switch (key) {
+ case Key.S:
+ projFile.Save ();
+ break;
+ case Key.W:
+ editorMutex.EnterWriteLock ();
+ if (e.Shift)
+ projFile.Redo (null);
+ else
+ projFile.Undo (null);
+ editorMutex.ExitWriteLock ();
+ break;
+ default:
+ Console.WriteLine ("");
+ break;
+ }
+ }
+
+ switch (key)
+ {
+ case Key.Back:
+ buffer.DeleteChar ();
+ break;
+ case Key.Clear:
+ break;
+ case Key.Delete:
+ if (buffer.SelectionIsEmpty)
+ MoveRight ();
+ else if (e.Shift)
+ IFace.Clipboard = buffer.SelectedText;
+ buffer.DeleteChar ();
+ break;
+ case Key.Enter:
+ case Key.KeypadEnter:
+ if (!buffer.SelectionIsEmpty)
+ buffer.DeleteChar ();
+ buffer.InsertLineBreak ();
+ break;
+ case Key.Escape:
+ buffer.ResetSelection ();
+ break;
+ case Key.Home:
+ if (e.Shift) {
+ if (buffer.SelectionIsEmpty)
+ buffer.SetSelStartPos ();
+ if (e.Control)
+ buffer.CurrentLine = 0;
+ buffer.CurrentColumn = 0;
+ buffer.SetSelEndPos ();
+ break;
+ }
+ buffer.ResetSelection ();
+ if (e.Control)
+ buffer.CurrentLine = 0;
+ buffer.CurrentColumn = 0;
+ break;
+ case Key.End:
+ if (e.Shift) {
+ if (buffer.SelectionIsEmpty)
+ buffer.SetSelStartPos ();
+ if (e.Control)
+ buffer.CurrentLine = int.MaxValue;
+ buffer.CurrentColumn = int.MaxValue;
+ buffer.SetSelEndPos ();
+ break;
+ }
+ buffer.ResetSelection ();
+ if (e.Control)
+ buffer.CurrentLine = int.MaxValue;
+ buffer.CurrentColumn = int.MaxValue;
+ break;
+ case Key.Insert:
+ if (e.Shift)
+ buffer.Insert (IFace.Clipboard);
+ else if (e.Control && !buffer.SelectionIsEmpty)
+ IFace.Clipboard = buffer.SelectedText;
+ break;
+ case Key.Left:
+ if (e.Shift) {
+ if (buffer.SelectionIsEmpty)
+ buffer.SetSelStartPos ();
+ if (e.Control)
+ buffer.GotoWordStart ();
+ else
+ MoveLeft ();
+ buffer.SetSelEndPos ();
+ break;
+ }
+ buffer.ResetSelection ();
+ if (e.Control)
+ buffer.GotoWordStart ();
+ else
+ MoveLeft();
+ break;
+ case Key.Right:
+ if (e.Shift) {
+ if (buffer.SelectionIsEmpty)
+ buffer.SetSelStartPos ();
+ if (e.Control)
+ buffer.GotoWordEnd ();
+ else
+ MoveRight ();
+ buffer.SetSelEndPos ();
+ break;
+ }
+ buffer.ResetSelection ();
+ if (e.Control)
+ buffer.GotoWordEnd ();
+ else
+ MoveRight ();
+ break;
+ case Key.Up:
+ if (e.Shift) {
+ if (buffer.SelectionIsEmpty)
+ buffer.SetSelStartPos ();
+ PrintedCurrentLine--;
+ buffer.SetSelEndPos ();
+ break;
+ }
+ buffer.ResetSelection ();
+ PrintedCurrentLine--;
+ break;
+ case Key.Down:
+ if (e.Shift) {
+ if (buffer.SelectionIsEmpty)
+ buffer.SetSelStartPos ();
+ PrintedCurrentLine++;
+ buffer.SetSelEndPos ();
+ break;
+ }
+ buffer.ResetSelection ();
+ PrintedCurrentLine++;
+ break;
+ case Key.Menu:
+ break;
+ case Key.NumLock:
+ break;
+ case Key.PageDown:
+ if (e.Shift) {
+ if (buffer.SelectionIsEmpty)
+ buffer.SetSelStartPos ();
+ PrintedCurrentLine += visibleLines;
+ buffer.SetSelEndPos ();
+ break;
+ }
+ buffer.ResetSelection ();
+ PrintedCurrentLine += visibleLines;
+ break;
+ case Key.PageUp:
+ if (e.Shift) {
+ if (buffer.SelectionIsEmpty)
+ buffer.SetSelStartPos ();
+ PrintedCurrentLine -= visibleLines;
+ buffer.SetSelEndPos ();
+ break;
+ }
+ buffer.ResetSelection ();
+ PrintedCurrentLine -= visibleLines;
+ break;
+ case Key.RWin:
+ break;
+ case Key.Tab:
+ if (e.Shift) {
+ if (buffer.SelectionIsEmpty ||
+ (buffer.SelectionStart.Y == buffer.SelectionEnd.Y)) {
+ //TODO
+ break;
+ }
+ for (int i = buffer.SelectionStart.Y; i <= buffer.SelectionEnd.Y; i++)
+ buffer.RemoveLeadingTab (i);
+ buffer.SetSelectionOnFullLines ();
+ } else {
+ if (buffer.SelectionIsEmpty ||
+ (buffer.SelectionStart.Y == buffer.SelectionEnd.Y)) {
+ buffer.Insert ("\t");
+ break;
+ }
+ for (int i = buffer.SelectionStart.Y; i <= buffer.SelectionEnd.Y; i++) {
+ buffer.UpdateLine (i, "\t" + buffer [i].Content);
+ }
+ }
+
+ break;
+ case Key.F8:
+ toogleFolding (buffer.CurrentLine);
+ break;
+ default:
+ break;
+ }
+ RegisterForGraphicUpdate();
+ }
+ public override void onKeyPress (object sender, KeyPressEventArgs e)
+ {
+ base.onKeyPress (sender, e);
+
+ buffer.Insert (e.KeyChar.ToString());
+ buffer.ResetSelection ();
+ }
+ #endregion
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+
+namespace Crow.Coding
+{
+ public struct TextFormatting {
+ public Color Foreground;
+ public Color Background;
+ public bool Bold;
+ public bool Italic;
+
+ public TextFormatting(Color fg, Color bg, bool bold = false, bool italic = false){
+ Foreground = fg;
+ Background = bg;
+ Bold = bold;
+ Italic = italic;
+ }
+ }
+}
+
--- /dev/null
+//
+// Token.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2017 jp
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+using System;
+
+namespace Crow.Coding
+{
+ public struct Token
+ {
+ public BufferParser.TokenType Type;
+ public string Content;
+ public Point Start;
+ public Point End;
+
+ public string PrintableContent {
+ get { return string.IsNullOrEmpty(Content) ? "" : Content.Replace("\t", new String(' ', Interface.TabSize)); }
+ }
+
+// public Token (TokenType tokType, string content = ""){
+// Type = tokType;
+// Content = content;
+// }
+
+ public bool IsNull { get { return IsEmpty && Type == BufferParser.TokenType.Unknown; }}
+ public bool IsEmpty { get { return string.IsNullOrEmpty(Content); }}
+
+ public static bool operator == (Token t, System.Enum tt){
+ return Convert.ToInt32(t.Type) == Convert.ToInt32(tt);
+ }
+ public static bool operator != (Token t, System.Enum tt){
+ return Convert.ToInt32(t.Type) != Convert.ToInt32(tt);
+ }
+ public static bool operator == (System.Enum tt, Token t){
+ return Convert.ToInt32(t.Type) == Convert.ToInt32(tt);
+ }
+ public static bool operator != (System.Enum tt, Token t){
+ return Convert.ToInt32(t.Type) != Convert.ToInt32(tt);
+ }
+
+ public static Token operator +(Token t, char c){
+ t.Content += c;
+ return t;
+ }
+ public static Token operator +(Token t, string s){
+ t.Content += s;
+ return t;
+ }
+ public override string ToString ()
+ {
+ return string.Format ("[Tok{2}->{3}:{0}: {1}]", Type,Content,Start,End);
+ }
+ }
+}
+
--- /dev/null
+//
+// EditPane.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using Crow;
+using System.Linq;
+
+namespace Crow.Coding
+{
+ public class EditPane : TemplatedGroup
+ {
+ public EditPane () {}
+
+ object selectedItemElement = null;
+
+ public override int SelectedIndex {
+ get {
+ return base.SelectedIndex;
+ }
+ set {
+ base.SelectedIndex = value;
+ }
+ }
+ public object SelectedItemElement {
+ get { return selectedItemElement; }
+ set {
+ if (selectedItemElement == value)
+ return;
+ selectedItemElement = value;
+ NotifyValueChanged ("SelectedItemElement", selectedItemElement);
+ }
+ }
+ }
+}
+
--- /dev/null
+//
+// Editor.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Threading;
+using System.Xml.Serialization;
+
+namespace Crow.Coding
+{
+ public abstract class Editor : ScrollingObject
+ {
+ #region CTOR
+ protected Editor ():base(){
+ Thread t = new Thread (backgroundThreadFunc);
+ t.IsBackground = true;
+ t.Start ();
+ }
+ #endregion
+
+ protected ReaderWriterLockSlim editorMutex = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
+ protected ProjectFile projFile = null;
+ Exception error = null;
+
+ public virtual ProjectFile ProjectNode
+ {
+ get { return projFile; }
+ set
+ {
+ if (projFile == value)
+ return;
+
+ if (projFile != null)
+ projFile.UnregisterEditor (this);
+
+ projFile = value;
+
+ if (projFile != null)
+ projFile.RegisterEditor (this);
+
+ NotifyValueChanged ("ProjectNode", projFile);
+ }
+ }
+ [XmlIgnore]public Exception Error {
+ get { return error; }
+ set {
+ if (error == value)
+ return;
+ error = value;
+ NotifyValueChanged ("Error", error);
+ NotifyValueChanged ("HasError", HasError);
+ }
+ }
+ [XmlIgnore]public bool HasError {
+ get { return error != null; }
+ }
+
+ protected abstract void updateEditorFromProjFile ();
+ protected abstract void updateProjFileFromEditor ();
+ protected abstract bool EditorIsDirty { get; set; }
+ protected virtual bool IsReady { get { return true; }}
+ protected virtual void updateCheckPostProcess () {}
+
+ protected void backgroundThreadFunc () {
+ while (true) {
+ if (IsReady) {
+ if (projFile != null) {
+ if (!projFile.RegisteredEditors [this]) {
+ projFile.RegisteredEditors [this] = true;
+ updateEditorFromProjFile ();
+ } else if (EditorIsDirty) {
+ EditorIsDirty = false;
+ updateProjFileFromEditor ();
+ }
+ updateCheckPostProcess ();
+ }
+ }
+ Thread.Sleep (10);
+ }
+ }
+ }
+}
+
--- /dev/null
+//
+// ImlVisualEditor.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2016 jp
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+using System;
+using Crow;
+using System.Threading;
+using System.Xml.Serialization;
+using System.ComponentModel;
+using System.IO;
+using System.Collections.Generic;
+using Crow.IML;
+using System.Text;
+using System.Xml;
+
+namespace Crow.Coding
+{
+ public class ImlVisualEditor : Editor
+ {
+ #region CTOR
+ public ImlVisualEditor () : base()
+ {
+ imlVE = new DesignInterface ();
+ }
+ #endregion
+
+ DesignInterface imlVE;
+ GraphicObject selectedItem;
+ ImlProjectItem imlProjFile;
+ Exception imlError = null;
+
+ bool drawGrid, snapToGrid;
+ int gridSpacing;
+
+ [DefaultValue(true)]
+ public bool DrawGrid {
+ get { return drawGrid; }
+ set {
+ if (drawGrid == value)
+ return;
+ drawGrid = value;
+ NotifyValueChanged ("DrawGrid", drawGrid);
+ RegisterForRedraw ();
+ }
+ }
+ [DefaultValue(true)]
+ public bool SnapToGrid {
+ get { return snapToGrid; }
+ set {
+ if (snapToGrid == value)
+ return;
+ snapToGrid = value;
+ NotifyValueChanged ("SnapToGrid", snapToGrid);
+ }
+ }
+ [DefaultValue(10)]
+ public int GridSpacing {
+ get { return gridSpacing; }
+ set {
+ if (gridSpacing == value)
+ return;
+ gridSpacing = value;
+ NotifyValueChanged ("GridSpacing", gridSpacing);
+ RegisterForRedraw ();
+ }
+ }
+ [XmlAttributeAttribute]public GraphicObject SelectedItem {
+ get { return selectedItem; }
+ set {
+ if (selectedItem == value)
+ return;
+ selectedItem = value;
+ NotifyValueChanged ("SelectedItem", selectedItem);
+ RegisterForRedraw ();
+ }
+ }
+ /// <summary>PoinprojFilever the widget</summary>
+ public virtual GraphicObject HoverWidget
+ {
+ get { return imlVE.HoverWidget; }
+ set {
+ if (HoverWidget == value)
+ return;
+
+ imlVE.HoverWidget = value;
+
+ NotifyValueChanged ("HoverWidget", HoverWidget);
+ }
+ }
+ [XmlIgnore]public List<LQIList> LQIs {
+ get { return imlVE.LQIs; }
+ }
+
+ public override ProjectFile ProjectNode {
+ get {
+ return base.ProjectNode;
+ }
+ set {
+ base.ProjectNode = value;
+ imlProjFile = projFile as ImlProjectItem;
+ imlVE.ProjFile = imlProjFile;
+ }
+ }
+
+ public List<GraphicObject> GraphicTree {
+ get { return imlVE.GraphicTree; }
+ }
+ protected override void updateProjFileFromEditor ()
+ {
+ try {
+ projFile.UpdateSource(this, imlProjFile.Instance.GetIML());
+ } catch (Exception ex) {
+ Error = ex.InnerException;
+ if (Monitor.IsEntered(imlVE.UpdateMutex))
+ Monitor.Exit (imlVE.UpdateMutex);
+ }
+ }
+ protected override void updateEditorFromProjFile () {
+ try {
+ string selItemDesignID = null;
+ if (SelectedItem!=null)
+ selItemDesignID = SelectedItem.design_id;
+ imlVE.ClearInterface();
+ Instantiator.NextInstantiatorID = 0;
+ imlVE.Styling = projFile.Project.solution.Styling;
+ imlVE.DefaultValuesLoader.Clear();
+ imlVE.DefaultTemplates = projFile.Project.solution.DefaultTemplates;
+ imlVE.Instantiators = new Dictionary<string, Instantiator>();
+
+ //prevent error on empty file
+ bool emptyFile = true;
+ string src = projFile.Source;
+ using (Stream s = new MemoryStream (Encoding.UTF8.GetBytes (src))) {
+ using (XmlReader itr = XmlReader.Create (s)) {
+ while(itr.Read()){
+ if (itr.NodeType == XmlNodeType.Element){
+ emptyFile = false;
+ break;
+ }
+ }
+ }
+ }
+ GraphicObject go = null;
+ Error = null;
+
+ if (emptyFile){
+ imlProjFile.Instance = null;
+ }else{
+ imlVE.LoadIMLFragment(src);
+ imlProjFile.Instance = imlVE.GraphicTree[0];
+ if (selItemDesignID!=null)
+ imlProjFile.Instance.FindByDesignID(selItemDesignID,out go);
+
+ }
+ SelectedItem = go;
+ } catch (Exception ex) {
+ Error = ex.InnerException;
+ if (Monitor.IsEntered(imlVE.UpdateMutex))
+ Monitor.Exit (imlVE.UpdateMutex);
+ }
+ }
+
+ protected override bool EditorIsDirty {
+ get { return imlProjFile == null ? false :
+ imlProjFile.Instance == null ? false : imlProjFile.Instance.design_HasChanged; }
+ set {
+ if (GraphicTree [0] != null)
+ GraphicTree [0].design_HasChanged = value;
+ }
+ }
+ protected override bool IsReady {
+ get { return updateEnabled && imlVE != null && imlProjFile != null; }
+ }
+ bool updateEnabled;
+ /// <summary>
+ /// use to disable update if tab is not the visible one
+ /// </summary>
+ public bool UpdateEnabled {
+ get { return updateEnabled; }
+ set {
+ if (value == updateEnabled)
+ return;
+ updateEnabled = value;
+ NotifyValueChanged ("UpdateEnabled", updateEnabled);
+ }
+ }
+ protected override void updateCheckPostProcess ()
+ {
+ imlVE.Update ();
+ bool isDirty = false;
+
+ lock (imlVE.RenderMutex)
+ isDirty = imlVE.IsDirty;
+
+ if (isDirty) {
+ lock (IFace.UpdateMutex)
+ RegisterForRedraw ();
+ }
+ }
+
+ #region GraphicObject overrides
+ public override void OnLayoutChanges (LayoutingType layoutType)
+ {
+ base.OnLayoutChanges (layoutType);
+ switch (layoutType) {
+ case LayoutingType.Width:
+ case LayoutingType.Height:
+ imlVE.ProcessResize (this.ClientRectangle.Size);
+ break;
+ }
+ }
+
+ public override void onMouseMove (object sender, MouseMoveEventArgs e)
+ {
+ base.onMouseMove (sender, e);
+
+ GraphicObject oldHW = HoverWidget;
+ Rectangle scr = this.ScreenCoordinates (this.getSlot ());
+ ProcessMouseMove (e.X - scr.X, e.Y - scr.Y);
+
+ if (oldHW == HoverWidget)
+ return;
+
+ if (draggedObj != null) {
+ if (isPossibleContainer (HoverWidget) && draggedObjContainer != HoverWidget) {
+ removeDraggedObjFrom ();
+ tryAddDraggedObjTo (HoverWidget);
+ }
+ }
+
+ RegisterForRedraw ();
+
+ }
+ public override void onMouseDown (object sender, MouseButtonEventArgs e)
+ {
+ //base.onMouseDown (sender, e);
+ SelectedItem = HoverWidget;
+
+ if (SelectedItem != null && projFile != null) {
+ projFile.CurrentLine = SelectedItem.design_line;
+ projFile.CurrentColumn = SelectedItem.design_column;
+ }
+
+ }
+
+ protected override void onDraw (Cairo.Context gr)
+ {
+ base.onDraw (gr);
+ if (!drawGrid)
+ return;
+
+
+ Rectangle cb = ClientRectangle;
+ const double gridLineWidth = 0.1;
+ double glhw = gridLineWidth / 2.0;
+ int nbLines = cb.Width / gridSpacing ;
+ double d = cb.Left + gridSpacing;
+ for (int i = 0; i < nbLines; i++) {
+ gr.MoveTo (d-glhw, cb.Y);
+ gr.LineTo (d-glhw, cb.Bottom);
+ d += gridSpacing;
+ }
+ nbLines = cb.Height / gridSpacing;
+ d = cb.Top + gridSpacing;
+ for (int i = 0; i < nbLines; i++) {
+ gr.MoveTo (cb.X, d - glhw);
+ gr.LineTo (cb.Right, d -glhw);
+ d += gridSpacing;
+ }
+ gr.LineWidth = gridLineWidth;
+ Foreground.SetAsSource (gr, cb);
+ gr.Stroke ();
+
+ lock (imlVE.RenderMutex) {
+ using (Cairo.Surface surf = new Cairo.ImageSurface (imlVE.bmp, Cairo.Format.Argb32,
+ imlVE.ClientRectangle.Width, imlVE.ClientRectangle.Height, imlVE.ClientRectangle.Width * 4)) {
+ gr.SetSourceSurface (surf, cb.Left, cb.Top);
+ gr.Paint ();
+ }
+ imlVE.IsDirty = false;
+ }
+
+ Rectangle hr;
+ if (HoverWidget != null) {
+ hr = HoverWidget.ScreenCoordinates (HoverWidget.getSlot ());
+// gr.SetSourceColor (Color.LightGray);
+// gr.DrawCote (new Cairo.PointD (hr.X, hr.Center.Y), new Cairo.PointD (hr.Right, hr.Center.Y));
+// gr.DrawCote (new Cairo.PointD (hr.Center.X, hr.Y), new Cairo.PointD (hr.Center.X, hr.Bottom));
+ //hr.Inflate (2);
+ gr.SetSourceColor (Color.LightGray);
+ gr.SetDash (new double[]{ 3.0, 3.0 }, 0.0);
+ gr.Rectangle (hr, 1.0);
+ }
+
+ if (SelectedItem?.Parent == null)
+ return;
+ hr = SelectedItem.ScreenCoordinates(SelectedItem.getSlot ());
+ hr.Inflate (1);
+ gr.LineWidth = 2;
+ gr.SetSourceColor (Color.Yellow);
+ gr.SetDash (new double[]{ 5.0, 3.0 },0.0);
+ gr.Rectangle (hr, 1.0);
+ }
+
+ protected override void onDragEnter (object sender, DragDropEventArgs e)
+ {
+ base.onDragEnter (sender, e);
+ GraphicObjectDesignContainer godc = e.DragSource.DataSource as GraphicObjectDesignContainer;
+ if (godc == null)
+ return;
+ createDraggedObj (godc.CrowType);
+ }
+ protected override void onDragLeave (object sender, DragDropEventArgs e)
+ {
+ base.onDragLeave (sender, e);
+
+ ClearDraggedObj ();
+ }
+ #endregion
+
+ #region draggedObj handling
+ public GraphicObject draggedObj = null;
+ public GraphicObject draggedObjContainer = null;
+
+ bool tryAddDraggedObjTo(GraphicObject g){
+ lock (imlVE.UpdateMutex) {
+ if (g.GetType ().IsSubclassOf (typeof(Container))) {
+ Container c = g as Container;
+ c.SetChild (draggedObj);
+ EditorIsDirty = true;
+ } else if (g.GetType ().IsSubclassOf (typeof(Group))) {
+ Group c = g as Group;
+ c.AddChild (draggedObj);
+ } else
+ return false;
+ EditorIsDirty = true;
+ draggedObjContainer = g;
+ }
+ return true;
+ }
+ bool isPossibleContainer (GraphicObject g){
+ if (g.GetType().IsSubclassOf(typeof(Container))){
+ Container c = g as Container;
+ return c.Child == null;
+ }
+ return g.GetType ().IsSubclassOf (typeof(Group));
+ }
+ void removeDraggedObjFrom(){
+ if (draggedObjContainer == null)
+ return;
+ lock (imlVE.UpdateMutex) {
+ if (draggedObjContainer.GetType().IsSubclassOf(typeof(Container))){
+ Container c = draggedObjContainer as Container;
+ c.SetChild (null);
+ EditorIsDirty = true;
+ //Console.WriteLine ("remove {0} from {1}", draggedObj, c);
+ }else if (draggedObjContainer.GetType().IsSubclassOf(typeof(Group))){
+ Group c = draggedObjContainer as Group;
+ c.RemoveChild (draggedObj);
+ EditorIsDirty = true;
+ //Console.WriteLine ("remove {0} from {1}", draggedObj, c);
+ }//else
+ // Console.WriteLine ("Error removing dragged obj");
+ }
+ draggedObjContainer = null;
+ }
+ void createDraggedObj (Type crowType) {
+ lock (imlVE.UpdateMutex) {
+ draggedObj = imlVE.CreateITorFromIMLFragment ("<" + crowType.Name + "/>").CreateInstance ();
+ }
+ }
+ public void ClearDraggedObj (bool removeFromTree = true) {
+ //Console.WriteLine ("Clear dragged obj {0}, remove from tree = {1}", draggedObj, removeFromTree);
+ if (removeFromTree)
+ removeDraggedObjFrom ();
+ draggedObjContainer = null;
+ if (draggedObj == null)
+ return;
+ if (removeFromTree)
+ draggedObj.Dispose ();
+ draggedObj = null;
+ }
+ #endregion
+
+
+ void WidgetCheckOver (GraphicObject go, MouseMoveEventArgs e){
+ Type tGo = go.GetType();
+ if (typeof(TemplatedGroup).IsAssignableFrom (tGo)) {
+
+ } else if (typeof(TemplatedContainer).IsAssignableFrom (tGo)) {
+ TemplatedContainer c = go as TemplatedContainer;
+ if (c.Content?.MouseIsIn (e.Position) == true) {
+ WidgetCheckOver (c.Content, e);
+ return;
+ }
+ } else if (typeof(TemplatedControl).IsAssignableFrom (tGo)) {
+ } else if (typeof(Group).IsAssignableFrom (tGo)) {
+ Group c = go as Group;
+ for (int i = c.Children.Count -1; i >= 0; i--) {
+ if (c.Children[i].MouseIsIn (e.Position)) {
+ WidgetCheckOver (c.Children[i], e);
+ return;
+ }
+ }
+ } else if (typeof(Crow.Container).IsAssignableFrom (tGo)) {
+ Crow.Container c = go as Crow.Container;
+ if (c.Child?.MouseIsIn (e.Position)==true) {
+ WidgetCheckOver (c.Child, e);
+ return;
+ }
+ }
+ HoverWidget = go;
+ WidgetMouseEnter (go, e);
+ }
+ void WidgetMouseLeave (GraphicObject go, MouseMoveEventArgs e){
+
+ }
+ void WidgetMouseEnter (GraphicObject go, MouseMoveEventArgs e){
+
+ }
+ void WidgetMouseMove (GraphicObject go, MouseMoveEventArgs e){}
+ public bool ProcessMouseMove(int x, int y)
+ {
+ int deltaX = x - imlVE.Mouse.X;
+ int deltaY = y - imlVE.Mouse.Y;
+ imlVE.Mouse.X = x;
+ imlVE.Mouse.Y = y;
+ MouseMoveEventArgs e = new MouseMoveEventArgs (x, y, deltaX, deltaY);
+ e.Mouse = imlVE.Mouse;
+
+ if (imlVE.ActiveWidget != null) {
+ //TODO, ensure object is still in the graphic tree
+ //send move evt even if mouse move outside bounds
+ WidgetMouseMove (imlVE.ActiveWidget, e);
+ return true;
+ }
+
+ if (HoverWidget != null) {
+ //TODO, ensure object is still in the graphic tree
+ //check topmost graphicobject first
+ GraphicObject tmp = HoverWidget;
+ GraphicObject topc = null;
+ while (tmp is GraphicObject) {
+ topc = tmp;
+ tmp = tmp.LogicalParent as GraphicObject;
+ }
+ int idxhw = imlVE.GraphicTree.IndexOf (topc);
+ if (idxhw != 0) {
+ int i = 0;
+ while (i < idxhw) {
+ if (imlVE.GraphicTree [i].LogicalParent == imlVE.GraphicTree [i].Parent) {
+ if (imlVE.GraphicTree [i].MouseIsIn (e.Position)) {
+ while (imlVE.HoverWidget != null) {
+ WidgetMouseLeave (imlVE.HoverWidget, e);
+ imlVE.HoverWidget = imlVE.HoverWidget.LogicalParent as GraphicObject;
+ }
+
+ WidgetCheckOver (GraphicTree [i], e);
+ return true;
+ }
+ }
+ i++;
+ }
+ }
+
+
+ if (imlVE.HoverWidget.MouseIsIn (e.Position)) {
+ WidgetCheckOver (imlVE.HoverWidget, (e));
+ return true;
+ } else {
+ WidgetMouseLeave (imlVE.HoverWidget, e);
+ //seek upward from last focused graph obj's
+ while (imlVE.HoverWidget.LogicalParent as GraphicObject != null) {
+ imlVE.HoverWidget = imlVE.HoverWidget.LogicalParent as GraphicObject;
+ if (imlVE.HoverWidget.MouseIsIn (e.Position)) {
+ WidgetCheckOver (imlVE.HoverWidget, e);
+ return true;
+ } else
+ WidgetMouseLeave (imlVE.HoverWidget, e);
+ }
+ }
+ }
+
+ //top level graphic obj's parsing
+ lock (imlVE.GraphicTree) {
+ for (int i = 0; i < imlVE.GraphicTree.Count; i++) {
+ GraphicObject g = imlVE.GraphicTree [i];
+ if (g.MouseIsIn (e.Position)) {
+ WidgetCheckOver (g, e);
+ return true;
+ }
+ }
+ }
+ imlVE.HoverWidget = null;
+ return false;
+
+ }
+
+ void GTView_SelectedItemChanged (object sender, SelectionChangeEventArgs e)
+ {
+ SelectedItem = e.NewValue as GraphicObject;
+ }
+ }
+}
--- /dev/null
+using System;
+using System.IO;
+using Crow;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+
+namespace Crow.Coding
+{
+ /// <summary>
+ /// base class for tokenizing sources
+ /// </summary>
+ public abstract class BufferParser
+ {
+ /// <summary>
+ /// Default tokens, this enum may be overriden in derived parser with the new keyword,
+ /// see XMLParser for example.
+ /// </summary>
+ public enum TokenType {
+ Unknown = 0,
+ WhiteSpace = 1,
+ NewLine = 2,
+ LineComment = 3,
+ BlockCommentStart = 4,
+ BlockComment = 5,
+ BlockCommentEnd = 6,
+ Preprocessor = 7,
+ Identifier = 8,
+ Keyword = 9,
+ OpenBlock = 10,
+ CloseBlock = 11,
+ StatementEnding = 12,
+ OperatorOrPunctuation = 13,
+ IntegerLitteral = 14,
+ RealLitteral = 15,
+ StringLitteralOpening = 16,
+ StringLitteralClosing = 17,
+ StringLitteral = 18,
+ CharLitteralOpening = 19,
+ CharLitteralClosing = 20,
+ CharLitteral = 21,
+ BoolLitteral = 22,
+ NullLitteral = 23,
+ Type = 24,
+ }
+
+ #region CTOR
+ public BufferParser (CodeBuffer _buffer)
+ {
+ buffer = _buffer;
+
+ buffer.LineUpadateEvent += Buffer_LineUpadateEvent;
+ //buffer.LineAdditionEvent += Buffer_LineAdditionEvent;;
+ buffer.LineRemoveEvent += Buffer_LineRemoveEvent;
+ buffer.BufferCleared += Buffer_BufferCleared;
+ }
+
+ #endregion
+
+ #region Buffer events handlers
+ void Buffer_BufferCleared (object sender, EventArgs e)
+ {
+
+ }
+ void Buffer_LineAdditionEvent (object sender, CodeBufferEventArgs e)
+ {
+
+ }
+ void Buffer_LineRemoveEvent (object sender, CodeBufferEventArgs e)
+ {
+ reparseSource ();
+ }
+ void Buffer_LineUpadateEvent (object sender, CodeBufferEventArgs e)
+ {
+ for (int i = 0; i < e.LineCount; i++)
+ TryParseBufferLine (e.LineStart + i);
+ reparseSource ();
+ }
+ #endregion
+
+ internal int currentLine = 0;
+ internal int currentColumn = 0;
+
+ int syntTreeDepth = 0;
+ public int SyntacticTreeDepth {
+ get { return syntTreeDepth;}
+ set {
+ syntTreeDepth = value;
+ if (syntTreeDepth > SyntacticTreeMaxDepth)
+ SyntacticTreeMaxDepth = syntTreeDepth;
+ }
+ }
+ public int SyntacticTreeMaxDepth = 0;
+
+ protected CodeBuffer buffer;
+ protected Token currentTok;
+ protected bool eol = true;
+ protected Point CurrentPosition {
+ get { return new Point (currentLine, currentColumn); }
+ set {
+ currentLine = value.Y;
+ currentColumn = value.X;
+ }
+ }
+
+ public Node RootNode;
+
+ public abstract void ParseCurrentLine();
+ public abstract void SyntaxAnalysis ();
+ public void reparseSource () {
+ for (int i = 0; i < buffer.LineCount; i++) {
+ if (!buffer[i].IsParsed)
+ TryParseBufferLine (i);
+ }
+ try {
+ SyntaxAnalysis ();
+ } catch (Exception ex) {
+ Debug.WriteLine ("Syntax Error: " + ex.ToString ());
+ if (ex is ParserException)
+ SetLineInError (ex as ParserException);
+ }
+ }
+ public void TryParseBufferLine(int lPtr) {
+ buffer [lPtr].exception = null;
+ currentLine = lPtr;
+ currentColumn = 0;
+ eol = false;
+
+ try {
+ ParseCurrentLine ();
+ } catch (Exception ex) {
+ Debug.WriteLine (ex.ToString ());
+ if (ex is ParserException)
+ SetLineInError (ex as ParserException);
+ }
+
+ }
+
+ public virtual void SetLineInError(ParserException ex) {
+ currentTok = default(Token);
+ if (ex.Line >= buffer.LineCount)
+ ex.Line = buffer.LineCount - 1;
+ if (buffer [ex.Line].IsFolded)
+ buffer.ToogleFolding (ex.Line);
+ buffer [ex.Line].SetLineInError (ex);
+ }
+ public virtual string LineBrkRegex {
+ get { return @"\r\n|\r|\n|\\\\n"; }
+ }
+ void updateFolding () {
+ // Stack<TokenList> foldings = new Stack<TokenList>();
+ // bool inStartTag = false;
+ //
+ // for (int i = 0; i < parser.Tokens.Count; i++) {
+ // TokenList tl = parser.Tokens [i];
+ // tl.foldingTo = null;
+ // int fstTK = tl.FirstNonBlankTokenIndex;
+ // if (fstTK > 0 && fstTK < tl.Count - 1) {
+ // if (tl [fstTK + 1] != XMLParser.TokenType.ElementName)
+ // continue;
+ // if (tl [fstTK] == XMLParser.TokenType.ElementStart) {
+ // //search closing tag
+ // int tkPtr = fstTK+2;
+ // while (tkPtr < tl.Count) {
+ // if (tl [tkPtr] == XMLParser.TokenType.ElementClosing)
+ //
+ // tkPtr++;
+ // }
+ // if (tl.EndingState == (int)XMLParser.States.Content)
+ // foldings.Push (tl);
+ // else if (tl.EndingState == (int)XMLParser.States.StartTag)
+ // inStartTag = true;
+ // continue;
+ // }
+ // if (tl [fstTK] == XMLParser.TokenType.ElementEnd) {
+ // TokenList tls = foldings.Pop ();
+ // int fstTKs = tls.FirstNonBlankTokenIndex;
+ // if (tls [fstTK + 1].Content == tl [fstTK + 1].Content) {
+ // tl.foldingTo = tls;
+ // continue;
+ // }
+ // parser.CurrentPosition = tls [fstTK + 1].Start;
+ // parser.SetLineInError(new ParserException(parser, "closing tag not corresponding"));
+ // }
+ //
+ // }
+ // }
+ }
+
+ #region low level parsing
+ protected void addCharToCurTok(char c, Point position){
+ currentTok.Start = position;
+ currentTok += c;
+ }
+ /// <summary>
+ /// Read one char from current position in buffer and store it into the current token
+ /// </summary>
+ /// <param name="startOfTok">if true, set the Start position of the current token to the current position</param>
+ protected void readToCurrTok(bool startOfTok = false){
+ if (startOfTok)
+ currentTok.Start = CurrentPosition;
+ currentTok += Read();
+ }
+ /// <summary>
+ /// read n char from the buffer and store it into the current token
+ /// </summary>
+ protected void readToCurrTok(int length) {
+ for (int i = 0; i < length; i++)
+ currentTok += Read ();
+ }
+ /// <summary>
+ /// Save current token into current TokensLine and raz current token
+ /// </summary>
+ protected void saveAndResetCurrentTok() {
+ currentTok.End = CurrentPosition;
+ buffer[currentLine].Tokens.Add (currentTok);
+ currentTok = default(Token);
+ }
+ /// <summary>
+ /// read one char and add current token to current TokensLine, current token is reset
+ /// </summary>
+ /// <param name="type">Type of the token</param>
+ /// <param name="startToc">set start of token to current position</param>
+ protected void readAndResetCurrentTok(System.Enum type, bool startToc = false) {
+ readToCurrTok ();
+ saveAndResetCurrentTok (type);
+ }
+ /// <summary>
+ /// Save current tok
+ /// </summary>
+ /// <param name="type">set the type of the tok</param>
+ protected void saveAndResetCurrentTok(System.Enum type) {
+ currentTok.Type = (TokenType)type;
+ saveAndResetCurrentTok ();
+ }
+ protected void setPreviousTokOfTypeTo (TokenType inType, TokenType newType) {
+ for (int i = currentLine; i >= 0; i--) {
+ int j = buffer [i].Tokens.Count - 1;
+ while (j >= 0) {
+ if (buffer [i].Tokens [j].Type == inType) {
+ Token t = buffer [i].Tokens [j];
+ t.Type = newType;
+ buffer [i].Tokens [j] = t;
+ return;
+ }
+ j--;
+ }
+ }
+ }
+ /// <summary>
+ /// Peek next char, emit '\n' if current column > buffer's line length
+ /// Throw error if eof is true
+ /// </summary>
+ protected virtual char Peek() {
+ if (eol)
+ throw new ParserException (currentLine, currentColumn, "Unexpected End of line");
+ return currentColumn < buffer [currentLine].Length ?
+ buffer [currentLine] [currentColumn] : '\n';
+ }
+ /// <summary>
+ /// Peek n char from buffer or less if remaining char in buffer's line is less than requested
+ /// if end of line is reached, no '\n' will be emitted, instead, empty string is returned. '\n' should be checked only
+ /// with single char Peek().
+ /// Throw error is eof is true
+ /// </summary>
+ /// <param name="length">Length.</param>
+ protected virtual string Peek(int length) {
+ if (eol)
+ throw new ParserException (currentLine, currentColumn, "Unexpected End of Line");
+ int lg = Math.Min(length, Math.Max (buffer [currentLine].Length - currentColumn, buffer [currentLine].Length - currentColumn - length));
+ if (lg == 0)
+ return "";
+ return buffer [currentLine].Content.Substring (currentColumn, lg);
+ }
+ /// <summary>
+ /// read one char from buffer at current position, if '\n' is read, current line is incremented
+ /// and column is reset to 0
+ /// </summary>
+ protected virtual char Read() {
+ char c = Peek ();
+ if (c == '\n')
+ eol = true;
+ currentColumn++;
+ return c;
+ }
+ protected virtual string Read(int charCount){
+ string tmp = "";
+ for (int i = 0; i < charCount; i++) {
+ if (eol)
+ break;
+ tmp += Read ();
+ }
+ return tmp;
+ }
+ /// <summary>
+ /// read until end of line is reached
+ /// </summary>
+ /// <returns>string read</returns>
+ protected virtual string ReadLine () {
+ StringBuilder tmp = new StringBuilder();
+ char c = Read ();
+ while (!eol) {
+ tmp.Append (c);
+ c = Read ();
+ }
+ return tmp.ToString();
+ }
+ /// <summary>
+ /// read until end expression is reached or end of line.
+ /// </summary>
+ /// <returns>string read minus the ending expression that has to be read after</returns>
+ /// <param name="endExp">Expression to search for</param>
+ protected virtual string ReadLineUntil (string endExp){
+ string tmp = "";
+
+ while (!eol) {
+ if (buffer [currentLine].Length - currentColumn - endExp.Length < 0) {
+ tmp += ReadLine();
+ break;
+ }
+ if (string.Equals (Peek (endExp.Length), endExp))
+ return tmp;
+ tmp += Read();
+ }
+ return tmp;
+ }
+ /// <summary>
+ /// skip white spaces, but not line break. Save spaces in a WhiteSpace token.
+ /// </summary>
+ protected void SkipWhiteSpaces () {
+ if (currentTok.Type != TokenType.Unknown)
+ throw new ParserException (currentLine, currentColumn, "current token should be reset to unknown (0) before skiping white spaces");
+ while (!eol) {
+ if (!char.IsWhiteSpace (Peek ())||Peek()=='\n')
+ break;
+ readToCurrTok (currentTok.Type == TokenType.Unknown);
+ currentTok.Type = TokenType.WhiteSpace;
+ }
+ if (currentTok.Type != TokenType.Unknown)
+ saveAndResetCurrentTok ();
+ }
+ #endregion
+
+ protected Node addChildNode (Node curNode, CodeLine cl, int tokPtr, string type = "") {
+ Node n = new Node () { Name = cl.Tokens [tokPtr].Content, StartLine = cl, Type = type };
+ curNode.AddChild (n);
+ if (cl.SyntacticNode == null)
+ cl.SyntacticNode = n;
+ SyntacticTreeDepth++;
+ return n;
+ }
+ protected void closeNodeAndGoUp (ref Node n, CodeLine cl, string type = ""){
+ while (n != null) {
+ if (n.Type == type) {
+ n.EndLine = cl;
+ n = n.Parent;
+ SyntacticTreeDepth--;
+ break;
+ }
+ n = n.Parent;
+ SyntacticTreeDepth--;
+ }
+ }
+ protected void closeNodeAndGoUp (ref Node n, CodeLine cl){
+ SyntacticTreeDepth--;
+ n.EndLine = cl;
+ n = n.Parent;
+ }
+
+ protected void initSyntaxAnalysis () {
+ RootNode = new Node () { Name = "RootNode", Type="Root" };
+ SyntacticTreeDepth = SyntacticTreeMaxDepth = 0;
+ }
+
+
+ protected void throwParserException(string msg){
+ throw new ParserException (currentLine, currentColumn, msg);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+using Crow;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text.RegularExpressions;
+using System.Linq;
+
+namespace Crow.Coding
+{
+ public class CSharpParser : BufferParser
+ {
+ #region keywords
+ string[] keywords = new string[] {
+ "abstract",
+ "as",
+ "ascending",
+ "async",
+ "await",
+ "base",
+ "bool",
+ "break",
+ "byte",
+ "case",
+ "catch",
+ "char",
+ "checked",
+ "class",
+ "const",
+ "continue",
+ "decimal",
+ "default",
+ "delegate",
+ "descending",
+ "do",
+ "double",
+ "dynamic",
+ "else",
+ "enum",
+ "equals",
+ "event",
+ "explicit",
+ "extern",
+ "false",
+ "finally",
+ "fixed",
+ "float",
+ "for",
+ "foreach",
+ "from",
+ "get",
+ "goto",
+ "group",
+ "if",
+ "implicit",
+ "in",
+ "int",
+ "interface",
+ "internal",
+ "is",
+ "join",
+ "let",
+ "lock",
+ "long",
+ "nameof",
+ "namespace",
+ "new",
+ "null",
+ "object",
+ "operator",
+ "orderby",
+ "out",
+ "override",
+ "params",
+ "partial",
+ "private",
+ "protected",
+ "public",
+ "readonly",
+ "ref",
+ "return",
+ "sbyte",
+ "sealed",
+ "select",
+ "set",
+ "short",
+ "sizeof",
+ "stackalloc",
+ "static",
+ "string",
+ "struct",
+ "switch",
+ "this",
+ "throw",
+ "true",
+ "try",
+ "typeof",
+ "uint",
+ "ulong",
+ "unchecked",
+ "unsafe",
+ "ushort",
+ "using",
+ "value",
+ "var",
+ "virtual",
+ "void",
+ "volatile",
+ "when",
+ "where",
+ "while",
+ "yield "
+ };
+ #endregion
+
+ public enum States
+ {
+ init,
+ BlockComment,
+ InNameSpace,
+ InClass,
+ InMember,
+ Unknown,
+ }
+
+ public CSharpParser (CodeBuffer _buffer) : base(_buffer)
+ {
+ }
+
+ #region Regular Expression for validity checks
+ static Regex rxValidChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}");
+ static Regex rxNameStartChar = new Regex(@"_|\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}");
+ static Regex rxNameChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}");
+ static Regex rxNewLineChar = new Regex(@"\u000D|\u000A|\u0085|\u2028|\u2029");
+ static Regex rxWhiteSpaceChar = new Regex(@"\p{Zs}|\u0009|\u000B|\u000C");
+ static Regex rxDecimal = new Regex(@"[0-9]+");
+ static Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+");
+
+ public static bool CharIsValidCharStartName (char c) {
+ return rxNameStartChar.IsMatch(new string(new char[]{c}));
+ }
+ public static bool CharIsValidCharName (char c) {
+ return rxNameChar.IsMatch(new string(new char[]{c}));
+ }
+
+ public bool nextCharIsValidCharStartName
+ {
+ get { return CharIsValidCharStartName(Peek()); }
+ }
+ public bool nextCharIsValidCharName
+ {
+ get { return CharIsValidCharName(Peek()); }
+ }
+ #endregion
+
+ States curState = States.init;
+ States savedState = States.init;
+
+ public override void ParseCurrentLine ()
+ {
+ //Debug.WriteLine (string.Format("parsing line:{0}", currentLine));
+ CodeLine cl = buffer [currentLine];
+ cl.Tokens = new List<Token> ();
+
+
+ //retrieve current parser state from previous line
+ if (currentLine > 0)
+ curState = (States)buffer[currentLine - 1].EndingState;
+ else
+ curState = States.init;
+
+ States previousEndingState = (States)cl.EndingState;
+
+ while (! eol) {
+ if (currentTok.IsNull)
+ SkipWhiteSpaces ();
+
+ if (curState == States.BlockComment) {
+ currentTok.Start = CurrentPosition;
+ currentTok.Type = (BufferParser.TokenType)TokenType.BlockComment;
+ currentTok += ReadLineUntil ("*/");
+ if (Peek (2) == "*/") {
+ readToCurrTok (2);
+ curState = savedState;
+ }
+ saveAndResetCurrentTok ();
+ continue;
+ }
+
+ switch (Peek()) {
+ case '\n':
+ eol = true;
+ if (!currentTok.IsNull)
+ saveAndResetCurrentTok ();
+ break;
+ case '#':
+ readToCurrTok (true);
+ currentTok += ReadLine ();
+ saveAndResetCurrentTok (TokenType.Preprocessor);
+ break;
+ case '/':
+ readToCurrTok (true);
+ switch (Peek ()) {
+ case '*':
+ readToCurrTok ();
+ currentTok += ReadLine ();
+ //currentTok.Type = (Parser.TokenType)TokenType.BlockComment;
+ savedState = curState;
+ curState = States.BlockComment;
+ saveAndResetCurrentTok (TokenType.BlockComment);
+ break;
+ case '/':
+ //readToCurrTok ();
+ currentTok += ReadLine ();
+ saveAndResetCurrentTok (TokenType.LineComment);
+ //currentTok.Type = (Parser.TokenType)TokenType.LineComment;
+ break;
+ default:
+ currentTok += ReadLine ();
+ saveAndResetCurrentTok (TokenType.Unknown);
+ break;
+ }
+ break;
+ case '{':
+ if (currentTok.IsNull)
+ readAndResetCurrentTok (TokenType.OpenBlock, true);
+ else
+ readToCurrTok ();
+ break;
+ case '}':
+ if (currentTok.IsNull)
+ readAndResetCurrentTok (TokenType.CloseBlock, true);
+ else
+ readToCurrTok ();
+ break;
+ case '\\'://unicode escape sequence
+ if (!(currentTok.Type == TokenType.Identifier ||
+ currentTok.IsEmpty || currentTok.Type == TokenType.StringLitteral || currentTok.Type == TokenType.CharLitteral)) {
+ saveAndResetCurrentTok ();
+ }
+ Point pos = CurrentPosition;
+ Read ();
+ char escChar = Read ();
+
+ if (escChar == 'u') {
+ char c = char.ConvertFromUtf32 (int.Parse (Read (4), System.Globalization.NumberStyles.HexNumber))[0];
+ if (currentTok.IsEmpty) {
+ if (!CharIsValidCharStartName (c))
+ throwParserException ("expecting identifier start");
+ currentTok.Start = pos;
+ currentTok.Type = TokenType.Identifier;
+ } else if (currentTok.Type == TokenType.Identifier) {
+ if (!CharIsValidCharName (c))
+ throwParserException ("expecting identifier valid char");
+ }
+ currentTok += c;
+ break;
+ }
+ currentTok += new String (new char[] { '\\', escChar });
+ break;
+ case '\'':
+ if (currentTok.IsNull) {
+ readAndResetCurrentTok (TokenType.CharLitteralOpening, true);
+ currentTok.Type = TokenType.CharLitteral;
+ } else if (currentTok.Type == TokenType.CharLitteral) {
+ saveAndResetCurrentTok ();
+ readAndResetCurrentTok (TokenType.CharLitteralClosing, true);
+ } else if (currentTok.Type == TokenType.StringLitteral){
+ readToCurrTok ();
+ } else
+ throwParserException ("unexpected character: (\')");
+ break;
+ case '"':
+ if (currentTok.IsNull) {
+ readAndResetCurrentTok (TokenType.StringLitteralOpening, true);
+ currentTok.Type = TokenType.StringLitteral;
+ } else if (currentTok.Type == TokenType.StringLitteral) {
+ saveAndResetCurrentTok ();
+ readAndResetCurrentTok (TokenType.StringLitteralClosing, true);
+ } else
+ throwParserException ("unexpected character: (\")");
+ break;
+ default:
+ if (currentTok.Type == TokenType.StringLitteral || currentTok.Type == TokenType.CharLitteral) {
+ readToCurrTok (currentTok.IsEmpty);
+ } else if (currentTok.IsNull) {
+ if (nextCharIsValidCharStartName) {
+ readToCurrTok (true);
+ while (nextCharIsValidCharName)
+ readToCurrTok ();
+
+ if (keywords.Contains (currentTok.Content))
+ saveAndResetCurrentTok (TokenType.Keyword);
+ else
+ saveAndResetCurrentTok (TokenType.Identifier);
+ continue;
+ } else
+ readAndResetCurrentTok(TokenType.Unknown, true);
+ } else
+ readAndResetCurrentTok(TokenType.Unknown, true);
+ break;
+ }
+ }
+
+ if (cl.EndingState != (int)curState && currentLine < buffer.LineCount - 1)
+ buffer [currentLine + 1].Tokens = null;
+
+ cl.EndingState = (int)curState;
+ }
+
+ public override void SyntaxAnalysis ()
+ {
+ initSyntaxAnalysis ();
+ Node currentNode = RootNode;
+
+ int ptrLine = 0;
+ while (ptrLine < buffer.LineCount) {
+ CodeLine cl = buffer [ptrLine];
+ if (cl.Tokens == null){
+ ptrLine++;
+ continue;
+ }
+ cl.SyntacticNode = null;
+
+ int tokPtr = 0;
+ bool onlyWhiteSpace = true;
+ while (tokPtr < cl.Tokens.Count) {
+ if (cl.Tokens [tokPtr].Type == TokenType.WhiteSpace) {
+ tokPtr++;
+ continue;
+ }
+
+ if (cl.Tokens [tokPtr].Type == TokenType.LineComment && onlyWhiteSpace) {
+ int startLine = ptrLine;
+ ptrLine++;
+ while (ptrLine < buffer.LineCount) {
+ int idx = buffer [ptrLine].FirstNonBlankTokIndex;
+ if (idx < 0)
+ break;
+ if (buffer [ptrLine].Tokens [idx].Type != TokenType.LineComment)
+ break;
+ ptrLine++;
+ }
+ ptrLine--;
+ if (ptrLine - startLine > 0) {
+ currentNode = addChildNode (currentNode, cl, tokPtr, "comment");
+ closeNodeAndGoUp (ref currentNode, buffer [ptrLine], "comment");
+ }
+ break;
+ }
+
+ switch (cl.Tokens [tokPtr].Type) {
+ case TokenType.OpenBlock:
+ currentNode = addChildNode (currentNode, cl, tokPtr);
+ break;
+ case TokenType.CloseBlock:
+ closeNodeAndGoUp (ref currentNode, cl);
+ break;
+ case TokenType.Preprocessor:
+ if (cl.Tokens [tokPtr].Content.StartsWith ("#region")) {
+ currentNode = addChildNode (currentNode, cl, tokPtr, "region");
+ } else if (cl.Tokens [tokPtr].Content.StartsWith ("#endregion")) {
+
+ closeNodeAndGoUp (ref currentNode, cl,"region");
+ }
+ break;
+ }
+ onlyWhiteSpace = false;
+ tokPtr++;
+ }
+ ptrLine++;
+ }
+ ptrLine = 0;
+ while (ptrLine < buffer.LineCount) {
+ CodeLine cl = buffer [ptrLine];
+ if (cl.IsFoldable) {
+ if (cl.SyntacticNode.Type == "comment" || cl.SyntacticNode.Type == "region")
+ cl.IsFolded = true;
+ }
+ ptrLine++;
+ }
+ }
+ }
+}
+
--- /dev/null
+using System;
+using Crow;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text.RegularExpressions;
+using System.Linq;
+
+namespace Crow.Coding
+{
+ public class StyleParser : BufferParser
+ {
+ enum States { init, classNames, members, value, endOfStatement }
+
+ public StyleParser (CodeBuffer _buffer) : base(_buffer)
+ {
+ }
+
+ #region Character ValidityCheck
+ static Regex rxValidChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}");
+ static Regex rxNameStartChar = new Regex(@"_|\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}");
+ static Regex rxNameChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}");
+ static Regex rxDecimal = new Regex(@"[0-9]+");
+ static Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+");
+
+ public bool nextCharIsValidCharStartName
+ {
+ get { return rxNameStartChar.IsMatch(new string(new char[]{Peek()})); }
+ }
+ public bool nextCharIsValidCharName
+ {
+ get { return rxNameChar.IsMatch(new string(new char[]{Peek()})); }
+ }
+ #endregion
+
+ States curState = States.classNames;
+
+ public override void ParseCurrentLine ()
+ {
+ //Debug.WriteLine (string.Format("parsing line:{0}", currentLine));
+ CodeLine cl = buffer [currentLine];
+ cl.Tokens = new List<Token> ();
+
+ //retrieve current parser state from previous line
+ if (currentLine > 0)
+ curState = (States)buffer[currentLine - 1].EndingState;
+ else
+ curState = States.init;
+
+ States previousEndingState = (States)cl.EndingState;
+
+ while (! eol) {
+ SkipWhiteSpaces ();
+
+ if (eol)
+ break;
+
+ if (Peek () == '\n') {
+ if (currentTok != TokenType.Unknown)
+ throw new ParserException (currentLine, currentColumn, "Unexpected end of line");
+ Read ();
+ eol = true;
+ continue;
+ }
+
+ switch (Peek()) {
+ case '/':
+ readToCurrTok (true);
+ switch (Peek ()) {
+ case '/':
+ currentTok += ReadLine ();
+ saveAndResetCurrentTok (TokenType.LineComment);
+ break;
+ default:
+ currentTok += ReadLine ();
+ saveAndResetCurrentTok (TokenType.Unknown);
+ break;
+ }
+ break;
+ case ',':
+ if (curState != States.init && curState != States.classNames )
+ throw new ParserException (currentLine, currentColumn, "Unexpected char ','");
+ readAndResetCurrentTok (TokenType.OperatorOrPunctuation, true);
+ curState = States.classNames;
+ break;
+ case '{':
+ if (!(curState == States.init || curState == States.classNames))
+ throw new ParserException (currentLine, currentColumn, "Unexpected char '{'");
+ readAndResetCurrentTok (TokenType.OpenBlock, true);
+ curState = States.members;
+ break;
+ case '}':
+ if (curState != States.members)
+ throw new ParserException (currentLine, currentColumn, "Unexpected char '}'");
+ readAndResetCurrentTok (TokenType.CloseBlock, true);
+ curState = States.classNames;
+ break;
+ case '=':
+ if (curState == States.classNames)
+ throw new ParserException (currentLine, currentColumn, "Unexpected char '='");
+ setPreviousTokOfTypeTo (TokenType.Type, TokenType.Identifier);
+ readAndResetCurrentTok (TokenType.OperatorOrPunctuation, true);
+ curState = States.value;
+ break;
+ case '"':
+ if (curState != States.value)
+ throw new ParserException (currentLine, currentColumn, "Unexpected char '\"'");
+ readAndResetCurrentTok (TokenType.StringLitteralOpening, true);
+
+ while (!eol) {
+ currentTok += ReadLineUntil ("\"");
+ if (currentTok.Content [currentTok.Content.Length - 1] == '\\')
+ readToCurrTok ();
+ else
+ break;
+ }
+ if (eol)
+ throw new ParserException (currentLine, currentColumn, "Unexpected end of line");
+ saveAndResetCurrentTok (TokenType.StringLitteral);
+
+ readAndResetCurrentTok (TokenType.StringLitteralClosing, true);
+ curState = States.endOfStatement;
+ break;
+ case ';':
+ if (curState != States.endOfStatement)
+ throw new ParserException (currentLine, currentColumn, "Unexpected end of statement");
+ readAndResetCurrentTok (TokenType.StatementEnding, true);
+ curState = States.members;
+ break;
+ default:
+ if (currentTok.Type != TokenType.Unknown)
+ throw new ParserException (currentLine, currentColumn, "error curtok not null");
+ if (curState == States.value)
+ throw new ParserException (currentLine, currentColumn, "expecting value enclosed in '\"'");
+ if (curState == States.endOfStatement)
+ throw new ParserException (currentLine, currentColumn, "expecting end of statement");
+
+ if (nextCharIsValidCharStartName) {
+ readToCurrTok (true);
+ while (nextCharIsValidCharName)
+ readToCurrTok ();
+ }
+ saveAndResetCurrentTok (TokenType.Type);
+ break;
+ }
+ }
+
+ if (cl.EndingState != (int)curState && currentLine < buffer.LineCount - 1)
+ buffer [currentLine + 1].Tokens = null;
+
+ cl.EndingState = (int)curState;
+ }
+ public override void SyntaxAnalysis ()
+ {
+ initSyntaxAnalysis ();
+ Node currentNode = RootNode;
+
+ for (int i = 0; i < buffer.LineCount; i++) {
+ CodeLine cl = buffer[i];
+ if (cl.Tokens == null)
+ continue;
+ cl.SyntacticNode = null;
+
+ int tokPtr = 0;
+ while (tokPtr < cl.Tokens.Count) {
+ switch (cl.Tokens [tokPtr].Type) {
+ case TokenType.OpenBlock:
+ currentNode = addChildNode (currentNode, cl, tokPtr, "style");
+ break;
+ case TokenType.CloseBlock:
+ closeNodeAndGoUp (ref currentNode, cl, "style");
+ break;
+ }
+ tokPtr++;
+ }
+ }
+ }
+ }
+}
+
--- /dev/null
+using System;
+using Crow;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using System.Diagnostics;
+using System.Linq;
+
+namespace Crow.Coding
+{
+ public class XMLParser : BufferParser
+ {
+ public new enum TokenType {
+ Unknown = BufferParser.TokenType.Unknown,
+ WhiteSpace = BufferParser.TokenType.WhiteSpace,
+ NewLine = BufferParser.TokenType.NewLine,
+ LineComment = BufferParser.TokenType.LineComment,
+ BlockCommentStart = BufferParser.TokenType.BlockCommentStart,
+ BlockComment = BufferParser.TokenType.BlockComment,
+ BlockCommentEnd = BufferParser.TokenType.BlockCommentEnd,
+ ElementName = BufferParser.TokenType.Identifier,
+ AttributeName = BufferParser.TokenType.Keyword,
+ ElementClosing = BufferParser.TokenType.StatementEnding,
+ Affectation = BufferParser.TokenType.OperatorOrPunctuation,
+ AttributeValueOpening = BufferParser.TokenType.StringLitteralOpening,
+ AttributeValueClosing = BufferParser.TokenType.StringLitteralClosing,
+ AttributeValue = BufferParser.TokenType.StringLitteral,
+ XMLDecl = BufferParser.TokenType.Preprocessor,
+ ElementStart = 50,
+ ElementEnd = 51,
+ }
+
+ public enum States
+ {
+ init, //first statement of prolog, xmldecl should only apear in this state
+ prolog, //misc before doctypedecl
+ InternalSubset, //doctype declaration subset
+ ExternalSubsetInit,
+ ExternalSubset,
+ BlockComment,
+ DTDEnd,//doctype finished
+ XML,//normal xml
+ StartTag,//inside start tag
+ Content,//after start tag with no closing slash
+ EndTag
+ }
+
+ #region CTOR
+ public XMLParser (CodeBuffer _buffer) : base(_buffer) {}
+ #endregion
+
+ enum Keywords
+ {
+ DOCTYPE,
+ ELEMENT,
+ ATTLIST,
+ ENTITY,
+ NOTATION
+ }
+
+ States curState = States.init;
+
+ #region Regular Expression for validity checks
+ //private static Regex rxValidChar = new Regex("[\u0020-\uD7FF]");
+ private static Regex rxValidChar = new Regex(@"\u0009|\u000A|\u000D|[\u0020-\uD7FF]|[\uE000-\uFFFD]"); //| [\u10000-\u10FFFF] unable to set those plans
+ private static Regex rxNameStartChar = new Regex(@":|[A-Z]|_|[a-z]|[\u00C0-\u00D6]|[\u00D8-\u00F6]|[\u00F8-\u02FF]|[\u0370-\u037D]|[\u037F-\u1FFF]|[\u200C-\u200D]|[\u2070-\u218F]|[\u2C00-\u2FEF]|[\u3001-\uD7FF]|[\uF900-\uFDCF]|[\uFDF0-\uFFFD]"); // | [\u10000-\uEFFFF]
+ private static Regex rxNameChar = new Regex(@":|[A-Z]|_|[a-z]|[\u00C0-\u00D6]|[\u00D8-\u00F6]|[\u00F8-\u02FF]|[\u0370-\u037D]|[\u037F-\u1FFF]|[\u200C-\u200D]|[\u2070-\u218F]|[\u2C00-\u2FEF]|[\u3001-\uD7FF]|[\uF900-\uFDCF]|[\uFDF0-\uFFFD]|-|\.|[0-9]|\u00B7|[\u0300-\u036F]|[\u203F-\u2040]");//[\u10000-\uEFFFF]|
+ private static Regex rxDecimal = new Regex(@"[0-9]+");
+ private static Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+");
+ private static Regex rxAttributeValue = new Regex(@"[^<]");
+ private static Regex rxEntityValue = new Regex(@"[^<]");
+ private static Regex rxPubidChar = new Regex(@"\u0020|\u000D|\u000A|[a-zA-Z0-9]|[-\(\)\+\,\./:=\?;!\*#@\$_%]");
+ #endregion
+
+ #region Character ValidityCheck
+ public bool nextCharIsValidCharStartName
+ {
+ get { return rxNameStartChar.IsMatch(new string(new char[]{Peek()})); }
+ }
+ public bool nextCharIsValidCharName
+ {
+ get { return rxNameChar.IsMatch(new string(new char[]{Peek()})); }
+ }
+ #endregion
+
+ public override void SetLineInError (ParserException ex)
+ {
+ base.SetLineInError (ex);
+ //buffer[ex.Line].Tokens.EndingState = (int)States.init;
+ }
+
+ public override void ParseCurrentLine ()
+ {
+ //Debug.WriteLine (string.Format("parsing line:{0}", currentLine));
+ CodeLine cl = buffer [currentLine];
+ cl.Tokens = new List<Token> ();
+
+ //retrieve current parser state from previous line
+ if (currentLine > 0)
+ curState = (States)buffer[currentLine - 1].EndingState;
+ else
+ curState = States.init;
+
+ States previousEndingState = (States)cl.EndingState;
+
+
+ while (! eol) {
+ SkipWhiteSpaces ();
+
+ if (eol)
+ break;
+
+ if (Peek () == '\n') {
+ if (currentTok != TokenType.Unknown)
+ throw new ParserException (currentLine, currentColumn, "Unexpected end of line");
+ Read ();
+ eol = true;
+ continue;
+ }
+
+ if (curState == States.BlockComment) {
+ if (currentTok != TokenType.Unknown)
+ Debugger.Break ();
+
+ currentTok.Start = CurrentPosition;
+ currentTok.Type = (BufferParser.TokenType)TokenType.BlockComment;
+ currentTok += ReadLineUntil ("-->");
+ if (Peek (3) == "-->") {
+ readToCurrTok (3);
+ curState = States.XML;
+ }
+ saveAndResetCurrentTok ();
+ continue;
+ }
+
+ switch (Peek()) {
+ case '<':
+ readToCurrTok (true);
+ switch (Peek()) {
+ case '?':
+ if (curState != States.init)
+ throw new ParserException (currentLine, currentColumn, "xml decl may appear only on first line");
+ readToCurrTok ();
+ currentTok += ReadLineUntil ("?>");
+ if (Peek (2) != "?>")
+ throw new ParserException (currentLine, currentColumn, "expecting '?>'");
+ readToCurrTok (2);
+ saveAndResetCurrentTok (TokenType.XMLDecl);
+ curState = States.prolog;
+ break;
+ case '!':
+ readToCurrTok ();
+ switch (Peek()) {
+ case '-':
+ readToCurrTok ();
+ if (Peek () != '-')
+ throw new ParserException (currentLine, currentColumn, "Expecting comment start tag");
+ readToCurrTok ();
+ currentTok += ReadLineUntil ("--");
+ if (Peek (3) == "-->") {
+ readToCurrTok (3);
+ }else
+ curState = States.BlockComment;
+ saveAndResetCurrentTok (TokenType.BlockComment);
+ break;
+ default:
+ throw new ParserException (currentLine, currentColumn, "error");
+ }
+ break;
+ default:
+ if (!(curState == States.Content || curState == States.XML || curState == States.init || curState == States.prolog))
+ throw new ParserException (currentLine, currentColumn, "Unexpected char: '<'");
+ if (Peek () == '/') {
+ curState = States.EndTag;
+ readToCurrTok ();
+ saveAndResetCurrentTok (TokenType.ElementEnd);
+ } else {
+ curState = States.StartTag;
+ saveAndResetCurrentTok (TokenType.ElementStart);
+ }
+
+ if (!nextCharIsValidCharStartName)
+ throw new ParserException (currentLine, currentColumn, "Expected element name");
+
+ readToCurrTok (true);
+ while (nextCharIsValidCharName)
+ readToCurrTok ();
+
+ saveAndResetCurrentTok (TokenType.ElementName);
+ break;
+ }
+ break;
+ case '/':
+ if (curState != States.StartTag)
+ throw new ParserException (currentLine, currentColumn, "Unexpected char: '/'");
+ readToCurrTok (true);
+ if (Peek () != '>')
+ throw new ParserException (currentLine, currentColumn, "Expecting '>'");
+ readAndResetCurrentTok (TokenType.ElementEnd);
+
+ curState = States.XML;
+ break;
+ case '>':
+ readAndResetCurrentTok (TokenType.ElementClosing, true);
+ switch (curState) {
+ case States.EndTag:
+ curState = States.XML;
+ break;
+ case States.StartTag:
+ curState = States.Content;
+ break;
+ default:
+ throw new ParserException (currentLine, currentColumn, "Unexpected char: '>'");
+ }
+ break;
+ default:
+ switch (curState) {
+ case States.StartTag:
+ if (!nextCharIsValidCharStartName)
+ throw new ParserException (currentLine, currentColumn, "Expected attribute name");
+ readToCurrTok (true);
+ while (nextCharIsValidCharName)
+ readToCurrTok ();
+ saveAndResetCurrentTok (TokenType.AttributeName);
+
+ SkipWhiteSpaces ();
+
+ if (Peek () != '=')
+ throw new ParserException (currentLine, currentColumn, "Expecting: '='");
+ readAndResetCurrentTok (TokenType.Affectation, true);
+
+ SkipWhiteSpaces ();
+
+ char openAttVal = Peek ();
+ if (openAttVal != '"' && openAttVal != '\'')
+ throw new ParserException (currentLine, currentColumn, "Expecting attribute value enclosed either in '\"' or in \"'\"");
+ readAndResetCurrentTok (TokenType.AttributeValueOpening, true);
+
+ currentTok.Start = CurrentPosition;
+ currentTok.Content = ReadLineUntil (new string (new char[]{ openAttVal }));
+ saveAndResetCurrentTok (TokenType.AttributeValue);
+
+ if (Peek () != openAttVal)
+ throw new ParserException (currentLine, currentColumn, string.Format ("Expecting {0}", openAttVal));
+ readAndResetCurrentTok (TokenType.AttributeValueClosing, true);
+ break;
+ default:
+ throw new ParserException (currentLine, currentColumn, "unexpected char: " + Peek ());
+ }
+ break;
+ }
+ }
+
+ if (cl.EndingState != (int)curState && currentLine < buffer.LineCount - 1)
+ buffer [currentLine + 1].Tokens = null;
+
+ cl.EndingState = (int)curState;
+ }
+
+ public override void SyntaxAnalysis ()
+ {
+ initSyntaxAnalysis ();
+ Node currentNode = RootNode;
+
+ for (int i = 0; i < buffer.LineCount; i++) {
+ CodeLine cl = buffer[i];
+ if (cl.Tokens == null)
+ continue;
+ cl.SyntacticNode = null;
+
+ int tokPtr = 0;
+ while (tokPtr < cl.Tokens.Count) {
+ switch ((XMLParser.TokenType)cl.Tokens [tokPtr].Type) {
+ case TokenType.ElementStart:
+ tokPtr++;
+ currentNode = addChildNode (currentNode, cl, tokPtr, "Element");
+ break;
+ case TokenType.ElementEnd:
+ tokPtr++;
+ if (tokPtr < cl.Tokens.Count) {
+ if ((XMLParser.TokenType)cl.Tokens [tokPtr].Type == TokenType.ElementName &&
+ cl.Tokens [tokPtr].Content != currentNode.Name)
+ throw new ParserException (currentLine, currentColumn, "Closing tag mismatch");
+ }
+ closeNodeAndGoUp (ref currentNode, cl, "Element");
+ break;
+ case TokenType.ElementClosing:
+ //currentNode = currentNode.Parent;
+ break;
+ default:
+ break;
+ }
+ tokPtr++;
+ }
+ }
+ }
+ }
+}
+
--- /dev/null
+//
+// SvgEditor.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.ComponentModel;
+using Cairo;
+
+namespace Crow.Coding
+{
+ public class SvgEditor : Editor
+ {
+ SvgPicture _pic = new SvgPicture();
+
+ int zoom;
+
+ [DefaultValue(100)]
+ public int Zoom {
+ get { return zoom; }
+ set {
+ if (zoom == value)
+ return;
+ zoom = value;
+ NotifyValueChanged ("Zoom", zoom);
+ updateMaxScrolls ();
+ RegisterForGraphicUpdate ();
+ }
+ }
+
+ void updateMaxScrolls() {
+ MaxScrollX = Math.Max(0, _pic.Dimensions.Width * zoom / 100 - Slot.Width);
+ MaxScrollY = Math.Max(0, _pic.Dimensions.Height * zoom / 100 - Slot.Height);
+
+ if (Slot.Width + MaxScrollX > 0)
+ NotifyValueChanged ("ChildWidthRatio", Slot.Width * Slot.Width / (Slot.Width + MaxScrollX));
+ else
+ NotifyValueChanged ("ChildWidthRatio", 0);
+
+ if (Slot.Height + MaxScrollY > 0)
+ NotifyValueChanged ("ChildHeightRatio", Slot.Height * Slot.Height / (Slot.Height + MaxScrollY));
+ else
+ NotifyValueChanged ("ChildHeightRatio", 0);
+ }
+ #region editor overrides
+ protected override void updateEditorFromProjFile ()
+ {
+ Error = null;
+ try {
+ editorMutex.EnterWriteLock();
+ _pic.LoadSvgFragment (projFile.Source);
+ _pic.Scaled = true;
+ _pic.KeepProportions = true;
+ } catch (Exception ex) {
+ Error = ex;
+ }
+ editorMutex.ExitWriteLock ();
+ updateMaxScrolls ();
+ RegisterForGraphicUpdate ();
+ }
+ protected override void updateProjFileFromEditor ()
+ {
+ throw new NotImplementedException ();
+ }
+ protected override bool EditorIsDirty {
+ get { return false; }
+ set {
+ throw new NotImplementedException ();
+ }
+ }
+ #endregion
+
+ #region GraphicObject overrides
+ protected override int measureRawSize (LayoutingType lt)
+ {
+ if (_pic == null)
+ return 2 * Margin;
+ //_pic = "#Crow.Images.Icons.IconAlerte.svg";
+ //TODO:take scalling in account
+ if (lt == LayoutingType.Width)
+ return _pic.Dimensions.Width + 2 * Margin;
+ else
+ return _pic.Dimensions.Height + 2 * Margin;
+ }
+ protected override void onDraw (Context gr)
+ {
+ base.onDraw (gr);
+
+ Rectangle r = ClientRectangle;
+ Foreground.SetAsSource (gr, r);
+ gr.Rectangle (r, 0.1);
+ gr.Stroke ();
+
+ r.Width = _pic.Dimensions.Width * zoom / 100;
+ r.Height = _pic.Dimensions.Height * zoom / 100;
+
+ gr.Save ();
+
+ editorMutex.EnterReadLock ();
+
+ gr.Translate (-ScrollX, -ScrollY);
+ if (_pic != null)
+ _pic.Paint (gr, r);
+ editorMutex.ExitReadLock ();
+
+ gr.Restore ();
+ }
+ public override void OnLayoutChanges (LayoutingType layoutType)
+ {
+ base.OnLayoutChanges (layoutType);
+ if ((layoutType | LayoutingType.Sizing) > 0)
+ updateMaxScrolls ();
+ }
+ #endregion
+ }
+}
+
{
public static partial class Extensions
{
+ public static string GetIcon(this GraphicObject go){
+ return "#Crow.Coding.icons.toolbox." + go.GetType().FullName + ".svg";
+ }
public static List<GraphicObject> GetChildren(this GraphicObject go){
Type goType = go.GetType();
if (typeof (Group).IsAssignableFrom (goType))
go.IFace.DragImageHeight = dis;
go.IFace.DragImageWidth = dis;
SvgPicture pic = new SvgPicture ();
- pic.Load (IconPath);
+ pic.Load (go.IFace, IconPath);
ImageSurface img = new ImageSurface (Format.Argb32, dis, dis);
using (Context ctx = new Context (img)) {
Rectangle r = new Rectangle (0, 0, dis, dis);
+++ /dev/null
-//
-// ImlVisualEditor.cs
-//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2016 jp
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-using System;
-using Crow;
-using System.Threading;
-using System.Xml.Serialization;
-using System.ComponentModel;
-using System.IO;
-using System.Collections.Generic;
-using Crow.IML;
-using System.Text;
-using System.Xml;
-
-namespace Crow.Coding
-{
- public class ImlVisualEditor : Editor
- {
- #region CTOR
- public ImlVisualEditor () : base()
- {
- imlVE = new DesignInterface ();
- }
- #endregion
-
- DesignInterface imlVE;
- GraphicObject selectedItem;
- ImlProjectItem imlProjFile;
- Exception imlError = null;
-
- bool drawGrid, snapToGrid;
- int gridSpacing;
-
- [DefaultValue(true)]
- public bool DrawGrid {
- get { return drawGrid; }
- set {
- if (drawGrid == value)
- return;
- drawGrid = value;
- NotifyValueChanged ("DrawGrid", drawGrid);
- RegisterForRedraw ();
- }
- }
- [DefaultValue(true)]
- public bool SnapToGrid {
- get { return snapToGrid; }
- set {
- if (snapToGrid == value)
- return;
- snapToGrid = value;
- NotifyValueChanged ("SnapToGrid", snapToGrid);
- }
- }
- [DefaultValue(10)]
- public int GridSpacing {
- get { return gridSpacing; }
- set {
- if (gridSpacing == value)
- return;
- gridSpacing = value;
- NotifyValueChanged ("GridSpacing", gridSpacing);
- RegisterForRedraw ();
- }
- }
- [XmlAttributeAttribute]public GraphicObject SelectedItem {
- get { return selectedItem; }
- set {
- if (selectedItem == value)
- return;
- selectedItem = value;
- NotifyValueChanged ("SelectedItem", selectedItem);
- RegisterForRedraw ();
- }
- }
- /// <summary>PoinprojFilever the widget</summary>
- public virtual GraphicObject HoverWidget
- {
- get { return imlVE.HoverWidget; }
- set {
- if (HoverWidget == value)
- return;
-
- imlVE.HoverWidget = value;
-
- NotifyValueChanged ("HoverWidget", HoverWidget);
- }
- }
- [XmlIgnore]public List<LQIList> LQIs {
- get { return imlVE.LQIs; }
- }
-
- public override ProjectFile ProjectNode {
- get {
- return base.ProjectNode;
- }
- set {
- base.ProjectNode = value;
- imlProjFile = projFile as ImlProjectItem;
- imlVE.ProjFile = imlProjFile;
- }
- }
-
- public List<GraphicObject> GraphicTree {
- get { return imlVE.GraphicTree; }
- }
- protected override void updateProjFileFromEditor ()
- {
- try {
- projFile.UpdateSource(this, imlProjFile.Instance.GetIML());
- } catch (Exception ex) {
- Error = ex.InnerException;
- if (Monitor.IsEntered(imlVE.UpdateMutex))
- Monitor.Exit (imlVE.UpdateMutex);
- }
- }
- protected override void updateEditorFromProjFile () {
- try {
- string selItemDesignID = null;
- if (SelectedItem!=null)
- selItemDesignID = SelectedItem.design_id;
- imlVE.ClearInterface();
- Instantiator.NextInstantiatorID = 0;
- imlVE.Styling = projFile.Project.solution.Styling;
- imlVE.DefaultValuesLoader.Clear();
- imlVE.DefaultTemplates = projFile.Project.solution.DefaultTemplates;
- imlVE.Instantiators = new Dictionary<string, Instantiator>();
-
- //prevent error on empty file
- bool emptyFile = true;
- string src = projFile.Source;
- using (Stream s = new MemoryStream (Encoding.UTF8.GetBytes (src))) {
- using (XmlReader itr = XmlReader.Create (s)) {
- while(itr.Read()){
- if (itr.NodeType == XmlNodeType.Element){
- emptyFile = false;
- break;
- }
- }
- }
- }
- GraphicObject go = null;
- Error = null;
-
- if (emptyFile){
- imlProjFile.Instance = null;
- }else{
- imlVE.LoadIMLFragment(src);
- imlProjFile.Instance = imlVE.GraphicTree[0];
- if (selItemDesignID!=null)
- imlProjFile.Instance.FindByDesignID(selItemDesignID,out go);
-
- }
- SelectedItem = go;
- } catch (Exception ex) {
- Error = ex.InnerException;
- if (Monitor.IsEntered(imlVE.UpdateMutex))
- Monitor.Exit (imlVE.UpdateMutex);
- }
- }
-
- protected override bool EditorIsDirty {
- get { return (bool)imlProjFile.Instance?.design_HasChanged; }
- set {
- if (GraphicTree [0] != null)
- GraphicTree [0].design_HasChanged = value;
- }
- }
- protected override bool IsReady {
- get { return imlVE != null && imlProjFile != null; }
- }
- protected override void updateCheckPostProcess ()
- {
- imlVE.Update ();
- bool isDirty = false;
-
- lock (imlVE.RenderMutex)
- isDirty = imlVE.IsDirty;
-
- if (isDirty) {
- lock (IFace.UpdateMutex)
- RegisterForRedraw ();
- }
- }
-
- #region GraphicObject overrides
- public override void OnLayoutChanges (LayoutingType layoutType)
- {
- base.OnLayoutChanges (layoutType);
- switch (layoutType) {
- case LayoutingType.Width:
- case LayoutingType.Height:
- imlVE.ProcessResize (this.ClientRectangle.Size);
- break;
- }
- }
-
- public override void onMouseMove (object sender, MouseMoveEventArgs e)
- {
- base.onMouseMove (sender, e);
-
- GraphicObject oldHW = HoverWidget;
- Rectangle scr = this.ScreenCoordinates (this.getSlot ());
- ProcessMouseMove (e.X - scr.X, e.Y - scr.Y);
-
- if (oldHW == HoverWidget)
- return;
-
- if (draggedObj != null) {
- if (isPossibleContainer (HoverWidget) && draggedObjContainer != HoverWidget) {
- removeDraggedObjFrom ();
- tryAddDraggedObjTo (HoverWidget);
- }
- }
-
- RegisterForRedraw ();
-
- }
- public override void onMouseDown (object sender, MouseButtonEventArgs e)
- {
- //base.onMouseDown (sender, e);
- SelectedItem = HoverWidget;
-
- if (SelectedItem != null && projFile != null) {
- projFile.CurrentLine = SelectedItem.design_line;
- projFile.CurrentColumn = SelectedItem.design_column;
- }
-
- }
-
- protected override void onDraw (Cairo.Context gr)
- {
- base.onDraw (gr);
- if (!drawGrid)
- return;
-
-
- Rectangle cb = ClientRectangle;
- const double gridLineWidth = 0.1;
- double glhw = gridLineWidth / 2.0;
- int nbLines = cb.Width / gridSpacing ;
- double d = cb.Left + gridSpacing;
- for (int i = 0; i < nbLines; i++) {
- gr.MoveTo (d-glhw, cb.Y);
- gr.LineTo (d-glhw, cb.Bottom);
- d += gridSpacing;
- }
- nbLines = cb.Height / gridSpacing;
- d = cb.Top + gridSpacing;
- for (int i = 0; i < nbLines; i++) {
- gr.MoveTo (cb.X, d - glhw);
- gr.LineTo (cb.Right, d -glhw);
- d += gridSpacing;
- }
- gr.LineWidth = gridLineWidth;
- Foreground.SetAsSource (gr, cb);
- gr.Stroke ();
-
- lock (imlVE.RenderMutex) {
- using (Cairo.Surface surf = new Cairo.ImageSurface (imlVE.bmp, Cairo.Format.Argb32,
- imlVE.ClientRectangle.Width, imlVE.ClientRectangle.Height, imlVE.ClientRectangle.Width * 4)) {
- gr.SetSourceSurface (surf, cb.Left, cb.Top);
- gr.Paint ();
- }
- imlVE.IsDirty = false;
- }
-
- Rectangle hr;
- if (HoverWidget != null) {
- hr = HoverWidget.ScreenCoordinates (HoverWidget.getSlot ());
-// gr.SetSourceColor (Color.LightGray);
-// gr.DrawCote (new Cairo.PointD (hr.X, hr.Center.Y), new Cairo.PointD (hr.Right, hr.Center.Y));
-// gr.DrawCote (new Cairo.PointD (hr.Center.X, hr.Y), new Cairo.PointD (hr.Center.X, hr.Bottom));
- //hr.Inflate (2);
- gr.SetSourceColor (Color.LightGray);
- gr.SetDash (new double[]{ 3.0, 3.0 }, 0.0);
- gr.Rectangle (hr, 1.0);
- }
-
- if (SelectedItem?.Parent == null)
- return;
- hr = SelectedItem.ScreenCoordinates(SelectedItem.getSlot ());
- hr.Inflate (1);
- gr.LineWidth = 2;
- gr.SetSourceColor (Color.Yellow);
- gr.SetDash (new double[]{ 5.0, 3.0 },0.0);
- gr.Rectangle (hr, 1.0);
- }
-
- protected override void onDragEnter (object sender, DragDropEventArgs e)
- {
- base.onDragEnter (sender, e);
- GraphicObjectDesignContainer godc = e.DragSource.DataSource as GraphicObjectDesignContainer;
- if (godc == null)
- return;
- createDraggedObj (godc.CrowType);
- }
- protected override void onDragLeave (object sender, DragDropEventArgs e)
- {
- base.onDragLeave (sender, e);
-
- ClearDraggedObj ();
- }
- #endregion
-
- #region draggedObj handling
- public GraphicObject draggedObj = null;
- public GraphicObject draggedObjContainer = null;
-
- bool tryAddDraggedObjTo(GraphicObject g){
- lock (imlVE.UpdateMutex) {
- if (g.GetType ().IsSubclassOf (typeof(Container))) {
- Container c = g as Container;
- c.SetChild (draggedObj);
- EditorIsDirty = true;
- } else if (g.GetType ().IsSubclassOf (typeof(Group))) {
- Group c = g as Group;
- c.AddChild (draggedObj);
- } else
- return false;
- EditorIsDirty = true;
- draggedObjContainer = g;
- }
- return true;
- }
- bool isPossibleContainer (GraphicObject g){
- if (g.GetType().IsSubclassOf(typeof(Container))){
- Container c = g as Container;
- return c.Child == null;
- }
- return g.GetType ().IsSubclassOf (typeof(Group));
- }
- void removeDraggedObjFrom(){
- if (draggedObjContainer == null)
- return;
- lock (imlVE.UpdateMutex) {
- if (draggedObjContainer.GetType().IsSubclassOf(typeof(Container))){
- Container c = draggedObjContainer as Container;
- c.SetChild (null);
- EditorIsDirty = true;
- //Console.WriteLine ("remove {0} from {1}", draggedObj, c);
- }else if (draggedObjContainer.GetType().IsSubclassOf(typeof(Group))){
- Group c = draggedObjContainer as Group;
- c.RemoveChild (draggedObj);
- EditorIsDirty = true;
- //Console.WriteLine ("remove {0} from {1}", draggedObj, c);
- }//else
- // Console.WriteLine ("Error removing dragged obj");
- }
- draggedObjContainer = null;
- }
- void createDraggedObj (Type crowType) {
- lock (imlVE.UpdateMutex) {
- draggedObj = imlVE.CreateITorFromIMLFragment ("<" + crowType.Name + "/>").CreateInstance ();
- }
- }
- public void ClearDraggedObj (bool removeFromTree = true) {
- //Console.WriteLine ("Clear dragged obj {0}, remove from tree = {1}", draggedObj, removeFromTree);
- if (removeFromTree)
- removeDraggedObjFrom ();
- draggedObjContainer = null;
- if (draggedObj == null)
- return;
- if (removeFromTree)
- draggedObj.Dispose ();
- draggedObj = null;
- }
- #endregion
-
-
- void WidgetCheckOver (GraphicObject go, MouseMoveEventArgs e){
- Type tGo = go.GetType();
- if (typeof(TemplatedGroup).IsAssignableFrom (tGo)) {
-
- } else if (typeof(TemplatedContainer).IsAssignableFrom (tGo)) {
- TemplatedContainer c = go as TemplatedContainer;
- if (c.Content?.MouseIsIn (e.Position) == true) {
- WidgetCheckOver (c.Content, e);
- return;
- }
- } else if (typeof(TemplatedControl).IsAssignableFrom (tGo)) {
- } else if (typeof(Group).IsAssignableFrom (tGo)) {
- Group c = go as Group;
- for (int i = c.Children.Count -1; i >= 0; i--) {
- if (c.Children[i].MouseIsIn (e.Position)) {
- WidgetCheckOver (c.Children[i], e);
- return;
- }
- }
- } else if (typeof(Crow.Container).IsAssignableFrom (tGo)) {
- Crow.Container c = go as Crow.Container;
- if (c.Child?.MouseIsIn (e.Position)==true) {
- WidgetCheckOver (c.Child, e);
- return;
- }
- }
- HoverWidget = go;
- WidgetMouseEnter (go, e);
- }
- void WidgetMouseLeave (GraphicObject go, MouseMoveEventArgs e){
-
- }
- void WidgetMouseEnter (GraphicObject go, MouseMoveEventArgs e){
-
- }
- void WidgetMouseMove (GraphicObject go, MouseMoveEventArgs e){}
- public bool ProcessMouseMove(int x, int y)
- {
- int deltaX = x - imlVE.Mouse.X;
- int deltaY = y - imlVE.Mouse.Y;
- imlVE.Mouse.X = x;
- imlVE.Mouse.Y = y;
- MouseMoveEventArgs e = new MouseMoveEventArgs (x, y, deltaX, deltaY);
- e.Mouse = imlVE.Mouse;
-
- if (imlVE.ActiveWidget != null) {
- //TODO, ensure object is still in the graphic tree
- //send move evt even if mouse move outside bounds
- WidgetMouseMove (imlVE.ActiveWidget, e);
- return true;
- }
-
- if (HoverWidget != null) {
- //TODO, ensure object is still in the graphic tree
- //check topmost graphicobject first
- GraphicObject tmp = HoverWidget;
- GraphicObject topc = null;
- while (tmp is GraphicObject) {
- topc = tmp;
- tmp = tmp.LogicalParent as GraphicObject;
- }
- int idxhw = imlVE.GraphicTree.IndexOf (topc);
- if (idxhw != 0) {
- int i = 0;
- while (i < idxhw) {
- if (imlVE.GraphicTree [i].LogicalParent == imlVE.GraphicTree [i].Parent) {
- if (imlVE.GraphicTree [i].MouseIsIn (e.Position)) {
- while (imlVE.HoverWidget != null) {
- WidgetMouseLeave (imlVE.HoverWidget, e);
- imlVE.HoverWidget = imlVE.HoverWidget.LogicalParent as GraphicObject;
- }
-
- WidgetCheckOver (GraphicTree [i], e);
- return true;
- }
- }
- i++;
- }
- }
-
-
- if (imlVE.HoverWidget.MouseIsIn (e.Position)) {
- WidgetCheckOver (imlVE.HoverWidget, (e));
- return true;
- } else {
- WidgetMouseLeave (imlVE.HoverWidget, e);
- //seek upward from last focused graph obj's
- while (imlVE.HoverWidget.LogicalParent as GraphicObject != null) {
- imlVE.HoverWidget = imlVE.HoverWidget.LogicalParent as GraphicObject;
- if (imlVE.HoverWidget.MouseIsIn (e.Position)) {
- WidgetCheckOver (imlVE.HoverWidget, e);
- return true;
- } else
- WidgetMouseLeave (imlVE.HoverWidget, e);
- }
- }
- }
-
- //top level graphic obj's parsing
- lock (imlVE.GraphicTree) {
- for (int i = 0; i < imlVE.GraphicTree.Count; i++) {
- GraphicObject g = imlVE.GraphicTree [i];
- if (g.MouseIsIn (e.Position)) {
- WidgetCheckOver (g, e);
- return true;
- }
- }
- }
- imlVE.HoverWidget = null;
- return false;
-
- }
-
- void GTView_SelectedItemChanged (object sender, SelectionChangeEventArgs e)
- {
- SelectedItem = e.NewValue as GraphicObject;
- }
- }
-}
: base (pi.Project, pi.node) {
cmdSave = new Crow.Command (new Action (() => Save ()))
- { Caption = "Save", Icon = new SvgPicture ("#Crow.Coding.ui.icons.inbox.svg"), CanExecute = false };
- cmdSave = new Crow.Command (new Action (() => SaveAs ()))
- { Caption = "Save As ..", Icon = new SvgPicture ("#Crow.Coding.ui.icons.inbox.svg"), CanExecute = false };
+ { Caption = "Save", Icon = new SvgPicture ("#Crow.Coding.ui.icons.inbox.svg"), CanExecute = false };
+ cmdSaveAs = new Crow.Command (new Action (() => SaveAs ()))
+ { Caption = "Save As ..", Icon = new SvgPicture ("#Crow.Coding.ui.icons.inbox.svg"), CanExecute = false };
cmdOpen = new Crow.Command (new Action (() => Open ()))
{ Caption = "Open", Icon = new SvgPicture ("#Crow.Coding.ui.icons.outbox.svg"), CanExecute = false };
cmdUndo = new Crow.Command (new Action (() => Undo (null)))
- { Caption = "Undo", Icon = new SvgPicture ("#Crow.Coding.icons.undo.svg"), CanExecute = false };
+ { Caption = "Undo", Icon = new SvgPicture ("#Crow.Coding.icons.undo.svg"), CanExecute = false };
cmdRedo = new Crow.Command (new Action (() => Redo (null)))
- { Caption = "Redo", Icon = new SvgPicture ("#Crow.Coding.icons.redo.svg"), CanExecute = false };
+ { Caption = "Redo", Icon = new SvgPicture ("#Crow.Coding.icons.redo.svg"), CanExecute = false };
Commands.Insert (0, cmdOpen);
Commands.Insert (1, cmdSave);
NotifyValueChanged ("Instance", instance);
}
}
+
+ public List<GraphicObject> GraphicTree {
+ get { return new List<GraphicObject> (new GraphicObject[] {instance}); }
+ }
+
+ void GTView_SelectedItemChanged (object sender, SelectionChangeEventArgs e){
+ SelectedItem = e.NewValue;
+ }
}
}
saveOpenedItemsInUserConfig ();
}
+ public void CloseSolution () {
+ while (openedItems.Count > 0) {
+ openedItems.RemoveElement (openedItems [0]);
+ }
+ while (toolboxItems.Count > 0) {
+ toolboxItems.RemoveElement (toolboxItems [0]);
+ }
+ NotifyValueChanged ("Projects", null);
+ }
/// <summary>
/// Solution name
/// </summary>
+++ /dev/null
-using System;
-using System.IO;
-using Crow;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Text;
-
-namespace Crow.Coding
-{
- /// <summary>
- /// base class for tokenizing sources
- /// </summary>
- public abstract class BufferParser
- {
- /// <summary>
- /// Default tokens, this enum may be overriden in derived parser with the new keyword,
- /// see XMLParser for example.
- /// </summary>
- public enum TokenType {
- Unknown = 0,
- WhiteSpace = 1,
- NewLine = 2,
- LineComment = 3,
- BlockCommentStart = 4,
- BlockComment = 5,
- BlockCommentEnd = 6,
- Preprocessor = 7,
- Identifier = 8,
- Keyword = 9,
- OpenBlock = 10,
- CloseBlock = 11,
- StatementEnding = 12,
- OperatorOrPunctuation = 13,
- IntegerLitteral = 14,
- RealLitteral = 15,
- StringLitteralOpening = 16,
- StringLitteralClosing = 17,
- StringLitteral = 18,
- CharLitteralOpening = 19,
- CharLitteralClosing = 20,
- CharLitteral = 21,
- BoolLitteral = 22,
- NullLitteral = 23,
- Type = 24,
- }
-
- #region CTOR
- public BufferParser (CodeBuffer _buffer)
- {
- buffer = _buffer;
-
- buffer.LineUpadateEvent += Buffer_LineUpadateEvent;
- //buffer.LineAdditionEvent += Buffer_LineAdditionEvent;;
- buffer.LineRemoveEvent += Buffer_LineRemoveEvent;
- buffer.BufferCleared += Buffer_BufferCleared;
- }
-
- #endregion
-
- #region Buffer events handlers
- void Buffer_BufferCleared (object sender, EventArgs e)
- {
-
- }
- void Buffer_LineAdditionEvent (object sender, CodeBufferEventArgs e)
- {
-
- }
- void Buffer_LineRemoveEvent (object sender, CodeBufferEventArgs e)
- {
- reparseSource ();
- }
- void Buffer_LineUpadateEvent (object sender, CodeBufferEventArgs e)
- {
- for (int i = 0; i < e.LineCount; i++)
- TryParseBufferLine (e.LineStart + i);
- reparseSource ();
- }
- #endregion
-
- internal int currentLine = 0;
- internal int currentColumn = 0;
-
- int syntTreeDepth = 0;
- public int SyntacticTreeDepth {
- get { return syntTreeDepth;}
- set {
- syntTreeDepth = value;
- if (syntTreeDepth > SyntacticTreeMaxDepth)
- SyntacticTreeMaxDepth = syntTreeDepth;
- }
- }
- public int SyntacticTreeMaxDepth = 0;
-
- protected CodeBuffer buffer;
- protected Token currentTok;
- protected bool eol = true;
- protected Point CurrentPosition {
- get { return new Point (currentLine, currentColumn); }
- set {
- currentLine = value.Y;
- currentColumn = value.X;
- }
- }
-
- public Node RootNode;
-
- public abstract void ParseCurrentLine();
- public abstract void SyntaxAnalysis ();
- public void reparseSource () {
- for (int i = 0; i < buffer.LineCount; i++) {
- if (!buffer[i].IsParsed)
- TryParseBufferLine (i);
- }
- try {
- SyntaxAnalysis ();
- } catch (Exception ex) {
- Debug.WriteLine ("Syntax Error: " + ex.ToString ());
- if (ex is ParserException)
- SetLineInError (ex as ParserException);
- }
- }
- public void TryParseBufferLine(int lPtr) {
- buffer [lPtr].exception = null;
- currentLine = lPtr;
- currentColumn = 0;
- eol = false;
-
- try {
- ParseCurrentLine ();
- } catch (Exception ex) {
- Debug.WriteLine (ex.ToString ());
- if (ex is ParserException)
- SetLineInError (ex as ParserException);
- }
-
- }
-
- public virtual void SetLineInError(ParserException ex) {
- currentTok = default(Token);
- if (ex.Line >= buffer.LineCount)
- ex.Line = buffer.LineCount - 1;
- if (buffer [ex.Line].IsFolded)
- buffer.ToogleFolding (ex.Line);
- buffer [ex.Line].SetLineInError (ex);
- }
- public virtual string LineBrkRegex {
- get { return @"\r\n|\r|\n|\\\\n"; }
- }
- void updateFolding () {
- // Stack<TokenList> foldings = new Stack<TokenList>();
- // bool inStartTag = false;
- //
- // for (int i = 0; i < parser.Tokens.Count; i++) {
- // TokenList tl = parser.Tokens [i];
- // tl.foldingTo = null;
- // int fstTK = tl.FirstNonBlankTokenIndex;
- // if (fstTK > 0 && fstTK < tl.Count - 1) {
- // if (tl [fstTK + 1] != XMLParser.TokenType.ElementName)
- // continue;
- // if (tl [fstTK] == XMLParser.TokenType.ElementStart) {
- // //search closing tag
- // int tkPtr = fstTK+2;
- // while (tkPtr < tl.Count) {
- // if (tl [tkPtr] == XMLParser.TokenType.ElementClosing)
- //
- // tkPtr++;
- // }
- // if (tl.EndingState == (int)XMLParser.States.Content)
- // foldings.Push (tl);
- // else if (tl.EndingState == (int)XMLParser.States.StartTag)
- // inStartTag = true;
- // continue;
- // }
- // if (tl [fstTK] == XMLParser.TokenType.ElementEnd) {
- // TokenList tls = foldings.Pop ();
- // int fstTKs = tls.FirstNonBlankTokenIndex;
- // if (tls [fstTK + 1].Content == tl [fstTK + 1].Content) {
- // tl.foldingTo = tls;
- // continue;
- // }
- // parser.CurrentPosition = tls [fstTK + 1].Start;
- // parser.SetLineInError(new ParserException(parser, "closing tag not corresponding"));
- // }
- //
- // }
- // }
- }
-
- #region low level parsing
- protected void addCharToCurTok(char c, Point position){
- currentTok.Start = position;
- currentTok += c;
- }
- /// <summary>
- /// Read one char from current position in buffer and store it into the current token
- /// </summary>
- /// <param name="startOfTok">if true, set the Start position of the current token to the current position</param>
- protected void readToCurrTok(bool startOfTok = false){
- if (startOfTok)
- currentTok.Start = CurrentPosition;
- currentTok += Read();
- }
- /// <summary>
- /// read n char from the buffer and store it into the current token
- /// </summary>
- protected void readToCurrTok(int length) {
- for (int i = 0; i < length; i++)
- currentTok += Read ();
- }
- /// <summary>
- /// Save current token into current TokensLine and raz current token
- /// </summary>
- protected void saveAndResetCurrentTok() {
- currentTok.End = CurrentPosition;
- buffer[currentLine].Tokens.Add (currentTok);
- currentTok = default(Token);
- }
- /// <summary>
- /// read one char and add current token to current TokensLine, current token is reset
- /// </summary>
- /// <param name="type">Type of the token</param>
- /// <param name="startToc">set start of token to current position</param>
- protected void readAndResetCurrentTok(System.Enum type, bool startToc = false) {
- readToCurrTok ();
- saveAndResetCurrentTok (type);
- }
- /// <summary>
- /// Save current tok
- /// </summary>
- /// <param name="type">set the type of the tok</param>
- protected void saveAndResetCurrentTok(System.Enum type) {
- currentTok.Type = (TokenType)type;
- saveAndResetCurrentTok ();
- }
- protected void setPreviousTokOfTypeTo (TokenType inType, TokenType newType) {
- for (int i = currentLine; i >= 0; i--) {
- int j = buffer [i].Tokens.Count - 1;
- while (j >= 0) {
- if (buffer [i].Tokens [j].Type == inType) {
- Token t = buffer [i].Tokens [j];
- t.Type = newType;
- buffer [i].Tokens [j] = t;
- return;
- }
- j--;
- }
- }
- }
- /// <summary>
- /// Peek next char, emit '\n' if current column > buffer's line length
- /// Throw error if eof is true
- /// </summary>
- protected virtual char Peek() {
- if (eol)
- throw new ParserException (currentLine, currentColumn, "Unexpected End of line");
- return currentColumn < buffer [currentLine].Length ?
- buffer [currentLine] [currentColumn] : '\n';
- }
- /// <summary>
- /// Peek n char from buffer or less if remaining char in buffer's line is less than requested
- /// if end of line is reached, no '\n' will be emitted, instead, empty string is returned. '\n' should be checked only
- /// with single char Peek().
- /// Throw error is eof is true
- /// </summary>
- /// <param name="length">Length.</param>
- protected virtual string Peek(int length) {
- if (eol)
- throw new ParserException (currentLine, currentColumn, "Unexpected End of Line");
- int lg = Math.Min(length, Math.Max (buffer [currentLine].Length - currentColumn, buffer [currentLine].Length - currentColumn - length));
- if (lg == 0)
- return "";
- return buffer [currentLine].Content.Substring (currentColumn, lg);
- }
- /// <summary>
- /// read one char from buffer at current position, if '\n' is read, current line is incremented
- /// and column is reset to 0
- /// </summary>
- protected virtual char Read() {
- char c = Peek ();
- if (c == '\n')
- eol = true;
- currentColumn++;
- return c;
- }
- protected virtual string Read(int charCount){
- string tmp = "";
- for (int i = 0; i < charCount; i++) {
- if (eol)
- break;
- tmp += Read ();
- }
- return tmp;
- }
- /// <summary>
- /// read until end of line is reached
- /// </summary>
- /// <returns>string read</returns>
- protected virtual string ReadLine () {
- StringBuilder tmp = new StringBuilder();
- char c = Read ();
- while (!eol) {
- tmp.Append (c);
- c = Read ();
- }
- return tmp.ToString();
- }
- /// <summary>
- /// read until end expression is reached or end of line.
- /// </summary>
- /// <returns>string read minus the ending expression that has to be read after</returns>
- /// <param name="endExp">Expression to search for</param>
- protected virtual string ReadLineUntil (string endExp){
- string tmp = "";
-
- while (!eol) {
- if (buffer [currentLine].Length - currentColumn - endExp.Length < 0) {
- tmp += ReadLine();
- break;
- }
- if (string.Equals (Peek (endExp.Length), endExp))
- return tmp;
- tmp += Read();
- }
- return tmp;
- }
- /// <summary>
- /// skip white spaces, but not line break. Save spaces in a WhiteSpace token.
- /// </summary>
- protected void SkipWhiteSpaces () {
- if (currentTok.Type != TokenType.Unknown)
- throw new ParserException (currentLine, currentColumn, "current token should be reset to unknown (0) before skiping white spaces");
- while (!eol) {
- if (!char.IsWhiteSpace (Peek ())||Peek()=='\n')
- break;
- readToCurrTok (currentTok.Type == TokenType.Unknown);
- currentTok.Type = TokenType.WhiteSpace;
- }
- if (currentTok.Type != TokenType.Unknown)
- saveAndResetCurrentTok ();
- }
- #endregion
-
- protected Node addChildNode (Node curNode, CodeLine cl, int tokPtr, string type = "") {
- Node n = new Node () { Name = cl.Tokens [tokPtr].Content, StartLine = cl, Type = type };
- curNode.AddChild (n);
- if (cl.SyntacticNode == null)
- cl.SyntacticNode = n;
- SyntacticTreeDepth++;
- return n;
- }
- protected void closeNodeAndGoUp (ref Node n, CodeLine cl, string type = ""){
- while (n != null) {
- if (n.Type == type) {
- n.EndLine = cl;
- n = n.Parent;
- SyntacticTreeDepth--;
- break;
- }
- n = n.Parent;
- SyntacticTreeDepth--;
- }
- }
- protected void closeNodeAndGoUp (ref Node n, CodeLine cl){
- SyntacticTreeDepth--;
- n.EndLine = cl;
- n = n.Parent;
- }
-
- protected void initSyntaxAnalysis () {
- RootNode = new Node () { Name = "RootNode", Type="Root" };
- SyntacticTreeDepth = SyntacticTreeMaxDepth = 0;
- }
-
-
- protected void throwParserException(string msg){
- throw new ParserException (currentLine, currentColumn, msg);
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-using System;
-using Crow;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Text.RegularExpressions;
-using System.Linq;
-
-namespace Crow.Coding
-{
- public class CSharpParser : BufferParser
- {
- #region keywords
- string[] keywords = new string[] {
- "abstract",
- "as",
- "ascending",
- "async",
- "await",
- "base",
- "bool",
- "break",
- "byte",
- "case",
- "catch",
- "char",
- "checked",
- "class",
- "const",
- "continue",
- "decimal",
- "default",
- "delegate",
- "descending",
- "do",
- "double",
- "dynamic",
- "else",
- "enum",
- "equals",
- "event",
- "explicit",
- "extern",
- "false",
- "finally",
- "fixed",
- "float",
- "for",
- "foreach",
- "from",
- "get",
- "goto",
- "group",
- "if",
- "implicit",
- "in",
- "int",
- "interface",
- "internal",
- "is",
- "join",
- "let",
- "lock",
- "long",
- "nameof",
- "namespace",
- "new",
- "null",
- "object",
- "operator",
- "orderby",
- "out",
- "override",
- "params",
- "partial",
- "private",
- "protected",
- "public",
- "readonly",
- "ref",
- "return",
- "sbyte",
- "sealed",
- "select",
- "set",
- "short",
- "sizeof",
- "stackalloc",
- "static",
- "string",
- "struct",
- "switch",
- "this",
- "throw",
- "true",
- "try",
- "typeof",
- "uint",
- "ulong",
- "unchecked",
- "unsafe",
- "ushort",
- "using",
- "value",
- "var",
- "virtual",
- "void",
- "volatile",
- "when",
- "where",
- "while",
- "yield "
- };
- #endregion
-
- public enum States
- {
- init,
- BlockComment,
- InNameSpace,
- InClass,
- InMember,
- Unknown,
- }
-
- public CSharpParser (CodeBuffer _buffer) : base(_buffer)
- {
- }
-
- #region Regular Expression for validity checks
- static Regex rxValidChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}");
- static Regex rxNameStartChar = new Regex(@"_|\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}");
- static Regex rxNameChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}");
- static Regex rxNewLineChar = new Regex(@"\u000D|\u000A|\u0085|\u2028|\u2029");
- static Regex rxWhiteSpaceChar = new Regex(@"\p{Zs}|\u0009|\u000B|\u000C");
- static Regex rxDecimal = new Regex(@"[0-9]+");
- static Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+");
-
- public static bool CharIsValidCharStartName (char c) {
- return rxNameStartChar.IsMatch(new string(new char[]{c}));
- }
- public static bool CharIsValidCharName (char c) {
- return rxNameChar.IsMatch(new string(new char[]{c}));
- }
-
- public bool nextCharIsValidCharStartName
- {
- get { return CharIsValidCharStartName(Peek()); }
- }
- public bool nextCharIsValidCharName
- {
- get { return CharIsValidCharName(Peek()); }
- }
- #endregion
-
- States curState = States.init;
- States savedState = States.init;
-
- public override void ParseCurrentLine ()
- {
- //Debug.WriteLine (string.Format("parsing line:{0}", currentLine));
- CodeLine cl = buffer [currentLine];
- cl.Tokens = new List<Token> ();
-
-
- //retrieve current parser state from previous line
- if (currentLine > 0)
- curState = (States)buffer[currentLine - 1].EndingState;
- else
- curState = States.init;
-
- States previousEndingState = (States)cl.EndingState;
-
- while (! eol) {
- if (currentTok.IsNull)
- SkipWhiteSpaces ();
-
- if (curState == States.BlockComment) {
- currentTok.Start = CurrentPosition;
- currentTok.Type = (BufferParser.TokenType)TokenType.BlockComment;
- currentTok += ReadLineUntil ("*/");
- if (Peek (2) == "*/") {
- readToCurrTok (2);
- curState = savedState;
- }
- saveAndResetCurrentTok ();
- continue;
- }
-
- switch (Peek()) {
- case '\n':
- eol = true;
- if (!currentTok.IsNull)
- saveAndResetCurrentTok ();
- break;
- case '#':
- readToCurrTok (true);
- currentTok += ReadLine ();
- saveAndResetCurrentTok (TokenType.Preprocessor);
- break;
- case '/':
- readToCurrTok (true);
- switch (Peek ()) {
- case '*':
- readToCurrTok ();
- currentTok += ReadLine ();
- //currentTok.Type = (Parser.TokenType)TokenType.BlockComment;
- savedState = curState;
- curState = States.BlockComment;
- saveAndResetCurrentTok (TokenType.BlockComment);
- break;
- case '/':
- //readToCurrTok ();
- currentTok += ReadLine ();
- saveAndResetCurrentTok (TokenType.LineComment);
- //currentTok.Type = (Parser.TokenType)TokenType.LineComment;
- break;
- default:
- currentTok += ReadLine ();
- saveAndResetCurrentTok (TokenType.Unknown);
- break;
- }
- break;
- case '{':
- if (currentTok.IsNull)
- readAndResetCurrentTok (TokenType.OpenBlock, true);
- else
- readToCurrTok ();
- break;
- case '}':
- if (currentTok.IsNull)
- readAndResetCurrentTok (TokenType.CloseBlock, true);
- else
- readToCurrTok ();
- break;
- case '\\'://unicode escape sequence
- if (!(currentTok.Type == TokenType.Identifier ||
- currentTok.IsEmpty || currentTok.Type == TokenType.StringLitteral || currentTok.Type == TokenType.CharLitteral)) {
- saveAndResetCurrentTok ();
- }
- Point pos = CurrentPosition;
- Read ();
- char escChar = Read ();
-
- if (escChar == 'u') {
- char c = char.ConvertFromUtf32 (int.Parse (Read (4), System.Globalization.NumberStyles.HexNumber))[0];
- if (currentTok.IsEmpty) {
- if (!CharIsValidCharStartName (c))
- throwParserException ("expecting identifier start");
- currentTok.Start = pos;
- currentTok.Type = TokenType.Identifier;
- } else if (currentTok.Type == TokenType.Identifier) {
- if (!CharIsValidCharName (c))
- throwParserException ("expecting identifier valid char");
- }
- currentTok += c;
- break;
- }
- currentTok += new String (new char[] { '\\', escChar });
- break;
- case '\'':
- if (currentTok.IsNull) {
- readAndResetCurrentTok (TokenType.CharLitteralOpening, true);
- currentTok.Type = TokenType.CharLitteral;
- } else if (currentTok.Type == TokenType.CharLitteral) {
- saveAndResetCurrentTok ();
- readAndResetCurrentTok (TokenType.CharLitteralClosing, true);
- } else if (currentTok.Type == TokenType.StringLitteral){
- readToCurrTok ();
- } else
- throwParserException ("unexpected character: (\')");
- break;
- case '"':
- if (currentTok.IsNull) {
- readAndResetCurrentTok (TokenType.StringLitteralOpening, true);
- currentTok.Type = TokenType.StringLitteral;
- } else if (currentTok.Type == TokenType.StringLitteral) {
- saveAndResetCurrentTok ();
- readAndResetCurrentTok (TokenType.StringLitteralClosing, true);
- } else
- throwParserException ("unexpected character: (\")");
- break;
- default:
- if (currentTok.Type == TokenType.StringLitteral || currentTok.Type == TokenType.CharLitteral) {
- readToCurrTok (currentTok.IsEmpty);
- } else if (currentTok.IsNull) {
- if (nextCharIsValidCharStartName) {
- readToCurrTok (true);
- while (nextCharIsValidCharName)
- readToCurrTok ();
-
- if (keywords.Contains (currentTok.Content))
- saveAndResetCurrentTok (TokenType.Keyword);
- else
- saveAndResetCurrentTok (TokenType.Identifier);
- continue;
- } else
- readAndResetCurrentTok(TokenType.Unknown, true);
- } else
- readAndResetCurrentTok(TokenType.Unknown, true);
- break;
- }
- }
-
- if (cl.EndingState != (int)curState && currentLine < buffer.LineCount - 1)
- buffer [currentLine + 1].Tokens = null;
-
- cl.EndingState = (int)curState;
- }
-
- public override void SyntaxAnalysis ()
- {
- initSyntaxAnalysis ();
- Node currentNode = RootNode;
-
- int ptrLine = 0;
- while (ptrLine < buffer.LineCount) {
- CodeLine cl = buffer [ptrLine];
- if (cl.Tokens == null){
- ptrLine++;
- continue;
- }
- cl.SyntacticNode = null;
-
- int tokPtr = 0;
- bool onlyWhiteSpace = true;
- while (tokPtr < cl.Tokens.Count) {
- if (cl.Tokens [tokPtr].Type == TokenType.WhiteSpace) {
- tokPtr++;
- continue;
- }
-
- if (cl.Tokens [tokPtr].Type == TokenType.LineComment && onlyWhiteSpace) {
- int startLine = ptrLine;
- ptrLine++;
- while (ptrLine < buffer.LineCount) {
- int idx = buffer [ptrLine].FirstNonBlankTokIndex;
- if (idx < 0)
- break;
- if (buffer [ptrLine].Tokens [idx].Type != TokenType.LineComment)
- break;
- ptrLine++;
- }
- ptrLine--;
- if (ptrLine - startLine > 0) {
- currentNode = addChildNode (currentNode, cl, tokPtr, "comment");
- closeNodeAndGoUp (ref currentNode, buffer [ptrLine], "comment");
- }
- break;
- }
-
- switch (cl.Tokens [tokPtr].Type) {
- case TokenType.OpenBlock:
- currentNode = addChildNode (currentNode, cl, tokPtr);
- break;
- case TokenType.CloseBlock:
- closeNodeAndGoUp (ref currentNode, cl);
- break;
- case TokenType.Preprocessor:
- if (cl.Tokens [tokPtr].Content.StartsWith ("#region")) {
- currentNode = addChildNode (currentNode, cl, tokPtr, "region");
- } else if (cl.Tokens [tokPtr].Content.StartsWith ("#endregion")) {
-
- closeNodeAndGoUp (ref currentNode, cl,"region");
- }
- break;
- }
- onlyWhiteSpace = false;
- tokPtr++;
- }
- ptrLine++;
- }
- ptrLine = 0;
- while (ptrLine < buffer.LineCount) {
- CodeLine cl = buffer [ptrLine];
- if (cl.IsFoldable) {
- if (cl.SyntacticNode.Type == "comment" || cl.SyntacticNode.Type == "region")
- cl.IsFolded = true;
- }
- ptrLine++;
- }
- }
- }
-}
-
+++ /dev/null
-//
-// CodeTextBuffer.cs
-//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2017 jp
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text.RegularExpressions;
-using System.Diagnostics;
-using System.Threading;
-
-namespace Crow.Coding
-{
- /// <summary>
- /// Code buffer, lines are arranged in a List<string>, new line chars are removed during string.split on '\n...',
- /// </summary>
- public class CodeBuffer
- {
- public ReaderWriterLockSlim editMutex = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
-
- //those events are handled in SourceEditor to help keeping sync between textbuffer,parser and editor.
- //modified lines are marked for reparse
- #region Events
- public event EventHandler<CodeBufferEventArgs> LineUpadateEvent;
- public event EventHandler<CodeBufferEventArgs> LineRemoveEvent;
- public event EventHandler<CodeBufferEventArgs> LineAdditionEvent;
- public event EventHandler<CodeBufferEventArgs> FoldingEvent;
- public event EventHandler BufferCleared;
- public event EventHandler SelectionChanged;
- public event EventHandler PositionChanged;
- #endregion
-
- string lineBreak = Interface.LineBreak;
- List<CodeLine> lines = new List<CodeLine>();
- public int longestLineIdx = 0;
- public int longestLineCharCount = 0;
- /// <summary>
- /// real position in char arrays, tab = 1 char
- /// </summary>
- int _currentLine = 0;
- int _currentCol = 0;
-
- public int LineCount { get { return lines.Count;}}
- public int IndexOf (CodeLine cl) {
- return lines.IndexOf (cl);
- }
-
- public CodeLine this[int i]
- {
- get { return lines[i]; }
- set {
- if (lines [i] == value)
- return;
- editMutex.EnterWriteLock ();
- lines [i] = value;
- editMutex.ExitWriteLock ();
- LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i));
- }
- }
-
- public void RemoveAt(int i){
- editMutex.EnterWriteLock ();
- lines.RemoveAt (i);
- editMutex.ExitWriteLock ();
- LineRemoveEvent.Raise (this, new CodeBufferEventArgs (i));
- }
- public void Insert(int i, string item){
- editMutex.EnterWriteLock ();
- lines.Insert (i, item);
- editMutex.ExitWriteLock ();
- LineAdditionEvent.Raise (this, new CodeBufferEventArgs (i));
- }
- public void Add(CodeLine item){
- editMutex.EnterWriteLock ();
- lines.Add (item);
- editMutex.ExitWriteLock ();
- LineAdditionEvent.Raise (this, new CodeBufferEventArgs (lines.Count - 1));
- }
- public void AddRange (string[] items){
- int start = lines.Count;
- editMutex.EnterWriteLock ();
- for (int i = 0; i < items.Length; i++)
- lines.Add (items [i]);
- editMutex.ExitWriteLock ();
- LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length));
- }
- public void AddRange (CodeLine[] items){
- int start = lines.Count;
- editMutex.EnterWriteLock ();
- lines.AddRange (items);
- editMutex.ExitWriteLock ();
- LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length));
- }
- public void Clear () {
- editMutex.EnterWriteLock ();
- longestLineCharCount = 0;
- lines.Clear ();
- editMutex.ExitWriteLock ();
- BufferCleared.Raise (this, null);
- }
- public void UpdateLine(int i, string newContent){
- editMutex.EnterWriteLock ();
- this [i].Content = newContent;
- editMutex.ExitWriteLock ();
- LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i));
- }
- public void AppenedLine(int i, string newContent){
- editMutex.EnterWriteLock ();
- this [i].Content += newContent;
- editMutex.ExitWriteLock ();
- LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i));
- }
- public void RemoveLeadingTab (int l) {
- if (this [l] [0] == '\t') {
- UpdateLine (l, this [l].Content.Substring (1));
- return;
- }
- int i = 0;
- while (i < Interface.TabSize) {
- if (this [l] [i] != ' ')
- break;
- i++;
- }
- if (i > 0)
- UpdateLine (l, this [l].Content.Substring (i));
- }
- public void ToogleFolding (int line) {
- if (!this [line].IsFoldable)
- return;
- editMutex.EnterWriteLock ();
- this [line].IsFolded = !this [line].IsFolded;
- editMutex.ExitWriteLock ();
- FoldingEvent.Raise (this, new CodeBufferEventArgs (line));
- }
- public void Load(string rawSource, string lineBrkRegex = @"\r\n|\r|\n|\\\n") {
- this.Clear();
-
- if (string.IsNullOrEmpty (rawSource))
- return;
-
- AddRange (Regex.Split (rawSource, lineBrkRegex));
-
- lineBreak = detectLineBreakKind (rawSource);
- }
-
- /// <summary>
- /// Finds the longest visual line as printed on screen with tabulation replaced with n spaces
- /// </summary>
- public void FindLongestVisualLine(){
- longestLineCharCount = 0;
- editMutex.EnterReadLock ();
- for (int i = 0; i < this.LineCount; i++) {
- if (lines[i].PrintableLength > longestLineCharCount) {
- longestLineCharCount = lines[i].PrintableLength;
- longestLineIdx = i;
- }
- }
- editMutex.ExitReadLock ();
- //Debug.WriteLine ("Longest line: {0}->{1}", longestLineIdx, longestLineCharCount);
- }
- /// <summary> line break could be '\r' or '\n' or '\r\n' </summary>
- static string detectLineBreakKind(string buffer){
- string strLB = "";
-
- if (string.IsNullOrEmpty(buffer))
- return Interface.LineBreak;
- int i = 0;
- while ( i < buffer.Length) {
- if (buffer [i] == '\r') {
- strLB += '\r';
- i++;
- }
- if (i < buffer.Length) {
- if (buffer [i] == '\r')
- return "\r";
- if (buffer[i] == '\n')
- strLB += '\n';
- }
- if (!string.IsNullOrEmpty (strLB))
- return strLB;
- i++;
- }
- return Interface.LineBreak;
- }
- /// <summary>
- /// return all lines with linebreaks
- /// </summary>
- public string FullText{
- get {
- if (lines.Count == 0)
- return "";
- string tmp = "";
- editMutex.EnterReadLock ();
- for (int i = 0; i < lines.Count -1; i++)
- tmp += lines [i].Content + this.lineBreak;
- tmp += lines [lines.Count - 1].Content;
- editMutex.ExitReadLock ();
- return tmp;
- }
- }
-
- /// <summary>
- /// unfolded and not in folds line count
- /// </summary>
- public int UnfoldedLines {
- get {
- int i = 0, vl = 0;
- editMutex.EnterReadLock ();
- while (i < LineCount) {
- if (this [i].IsFolded) {
- i = GetEndNodeIndex (i);
- if (i < 0) {
- Console.WriteLine ("error folding");
- break;
- }
- }
- i++;
- vl++;
- }
- editMutex.ExitReadLock ();
- //Debug.WriteLine ("unfolded lines: " + vl);
- return vl;
- }
- }
-
- /// <summary>
- /// convert visual position to buffer position
- /// </summary>
- Point getBuffPos (Point visualPos) {
- int i = 0;
- int buffCol = 0;
- while (i < visualPos.X) {
- if (this [visualPos.Y] [buffCol] == '\t')
- i += Interface.TabSize;
- else
- i++;
- buffCol++;
- }
- return new Point (buffCol, visualPos.Y);
- }
-
- public int GetEndNodeIndex (int line) {
- return IndexOf (this [line].SyntacticNode.EndLine);
- }
-
- int ConverteTabulatedPosOfCurLine (int column) {
- int tmp = 0;
- int i = 0;
- while (i < lines [_currentLine].Content.Length){
- if (lines [_currentLine].Content [i] == '\t')
- tmp += 4;
- else
- tmp++;
- if (tmp > column)
- break;
- i++;
- }
- return i;
- }
-
- public int CurrentTabulatedColumn {
- get {
- return lines [_currentLine].Content.Substring (0, _currentCol).
- Replace ("\t", new String (' ', Interface.TabSize)).Length;
- }
- }
- /// <summary>
- /// Gets visual position computed from actual buffer position
- /// </summary>
-// public Point TabulatedPosition {
-// get { return new Point (TabulatedColumn, _currentLine); }
-// }
- /// <summary>
- /// set buffer current position from visual position
- /// </summary>
-// public void SetBufferPos(Point tabulatedPosition) {
-// CurrentPosition = getBuffPos(tabulatedPosition);
-// }
-
- #region Editing and moving cursor
- Point selStartPos = -1; //selection start (row,column)
- Point selEndPos = -1; //selection end (row,column)
-
- public bool SelectionInProgress { get { return selStartPos >= 0; }}
- public void SetSelStartPos () {
- selStartPos = selEndPos = CurrentPosition;
- SelectionChanged.Raise (this, null);
- }
- public void SetSelEndPos () {
- selEndPos = CurrentPosition;
- SelectionChanged.Raise (this, null);
- }
- public void SetSelectionOnFullLines () {
- if (!SelectionInProgress)
- return;
- Point s = new Point (0, SelectionStart.Y);
- Point e = new Point (this [SelectionEnd.Y].Length, SelectionEnd.Y);
- selStartPos = s;
- selEndPos = e;
- SelectionChanged.Raise (this, null);
- }
- /// <summary>
- /// Set selection in buffer to -1, empty selection
- /// </summary>
- public void ResetSelection () {
- selStartPos = selEndPos = -1;
- SelectionChanged.Raise (this, null);
- }
-
- public string SelectedText {
- get {
- if (SelectionIsEmpty)
- return "";
- Point selStart = SelectionStart;
- Point selEnd = SelectionEnd;
- if (selStart.Y == selEnd.Y)
- return this [selStart.Y].Content.Substring (selStart.X, selEnd.X - selStart.X);
- string tmp = "";
- tmp = this [selStart.Y].Content.Substring (selStart.X);
- for (int l = selStart.Y + 1; l < selEnd.Y; l++) {
- tmp += Interface.LineBreak + this [l].Content;
- }
- tmp += Interface.LineBreak + this [selEnd.Y].Content.Substring (0, selEnd.X);
- return tmp;
- }
- }
- /// <summary>
- /// ordered selection start and end positions in char units
- /// </summary>
- public Point SelectionStart {
- get { return selEndPos < 0 || selStartPos.Y < selEndPos.Y ? selStartPos :
- selStartPos.Y > selEndPos.Y ? selEndPos :
- selStartPos.X < selEndPos.X ? selStartPos : selEndPos; }
- }
- public Point SelectionEnd {
- get { return selEndPos < 0 || selStartPos.Y > selEndPos.Y ? selStartPos :
- selStartPos.Y < selEndPos.Y ? selEndPos :
- selStartPos.X > selEndPos.X ? selStartPos : selEndPos; }
- }
- public bool SelectionIsEmpty
- { get { return selEndPos == selStartPos; } }
- int requestedColumn = -1;
- /// <summary>
- /// Current column in buffer coordinate, tabulation = 1 char
- /// </summary>
- public int CurrentColumn{
- get { return _currentCol; }
- set {
- if (value == _currentCol)
- return;
-
- editMutex.EnterReadLock ();
-
- if (value < 0)
- _currentCol = 0;
- else if (value > lines [_currentLine].Length)
- _currentCol = lines [_currentLine].Length;
- else
- _currentCol = value;
-
- requestedColumn = CurrentTabulatedColumn;
-
- editMutex.ExitReadLock ();
-
- PositionChanged.Raise (this, null);
- }
- }
- /// <summary>
- /// Current row in buffer coordinate, tabulation = 1 char
- /// </summary>
- public int CurrentLine{
- get { return _currentLine; }
- set {
- if (value == _currentLine)
- return;
-
- editMutex.EnterReadLock ();
-
- if (value >= lines.Count)
- _currentLine = lines.Count-1;
- else if (value < 0)
- _currentLine = 0;
- else
- _currentLine = value;
-// if (_currentCol < 0)
-// requestedColumn = tabu _currentCol;
- int tabulatedRequestedCol = ConverteTabulatedPosOfCurLine(requestedColumn);
- if (requestedColumn > lines [_currentLine].PrintableLength)
- _currentCol = lines [_currentLine].Length;
- else
- //_currentCol = requestedColumn;
- _currentCol = tabulatedRequestedCol;
- //Debug.WriteLine ("buff cur line: " + _currentLine);
-
- editMutex.ExitReadLock();
-
- PositionChanged.Raise (this, null);
- }
- }
- public CodeLine CurrentCodeLine {
- get { return this [_currentLine]; }
- }
- /// <summary>
- /// Current position in buffer coordinate, tabulation = 1 char
- /// </summary>
- public Point CurrentPosition {
- get { return new Point(CurrentColumn, CurrentLine); }
-// set {
-// _currentCol = value.X;
-// _currentLine = value.Y;
-// }
- }
- /// <summary>
- /// get char at current position in buffer
- /// </summary>
- protected Char CurrentChar { get { return lines [CurrentLine] [CurrentColumn]; } }
-
- public void GotoWordStart(){
- if (this[CurrentLine].Length == 0)
- return;
- CurrentColumn--;
- //skip white spaces
- while (!char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn > 0)
- CurrentColumn--;
- while (char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn > 0)
- CurrentColumn--;
- if (!char.IsLetterOrDigit (this.CurrentChar))
- CurrentColumn++;
- }
- public void GotoWordEnd(){
- //skip white spaces
- if (CurrentColumn >= this [CurrentLine].Length - 1)
- return;
- while (!char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn < this [CurrentLine].Length-1)
- CurrentColumn++;
- while (char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn < this [CurrentLine].Length-1)
- CurrentColumn++;
- if (char.IsLetterOrDigit (this.CurrentChar))
- CurrentColumn++;
- }
- public void DeleteChar()
- {
- editMutex.EnterWriteLock ();
- if (SelectionIsEmpty) {
- if (CurrentColumn == 0) {
- if (CurrentLine == 0) {
- editMutex.ExitWriteLock ();
- return;
- }
- CurrentLine--;
- CurrentColumn = this [CurrentLine].Length;
- AppenedLine (CurrentLine, this [CurrentLine + 1].Content);
- RemoveAt (CurrentLine + 1);
- editMutex.ExitWriteLock ();
- return;
- }
- CurrentColumn--;
- UpdateLine (CurrentLine, this [CurrentLine].Content.Remove (CurrentColumn, 1));
- } else {
- int linesToRemove = SelectionEnd.Y - SelectionStart.Y + 1;
- int l = SelectionStart.Y;
-
- if (linesToRemove > 0) {
- UpdateLine (l, this [l].Content.Remove (SelectionStart.X, this [l].Length - SelectionStart.X) +
- this [SelectionEnd.Y].Content.Substring (SelectionEnd.X, this [SelectionEnd.Y].Length - SelectionEnd.X));
- l++;
- for (int c = 0; c < linesToRemove - 1; c++)
- RemoveAt (l);
- CurrentLine = SelectionStart.Y;
- CurrentColumn = SelectionStart.X;
- } else
- UpdateLine (l, this [l].Content.Remove (SelectionStart.X, SelectionEnd.X - SelectionStart.X));
- CurrentColumn = SelectionStart.X;
- ResetSelection ();
- }
- editMutex.ExitWriteLock ();
- }
- /// <summary>
- /// Insert new string at caret position, should be sure no line break is inside.
- /// </summary>
- /// <param name="str">String.</param>
- public void Insert(string str)
- {
- if (!SelectionIsEmpty)
- this.DeleteChar ();
- string[] strLines = Regex.Split (str, "\r\n|\r|\n|" + @"\\n").ToArray();
- UpdateLine (CurrentLine, this [CurrentLine].Content.Insert (CurrentColumn, strLines[0]));
- CurrentColumn += strLines[0].Length;
- for (int i = 1; i < strLines.Length; i++) {
- InsertLineBreak ();
- UpdateLine (CurrentLine, this [CurrentLine].Content.Insert (CurrentColumn, strLines[i]));
- CurrentColumn += strLines[i].Length;
- }
- }
- /// <summary>
- /// Insert a line break.
- /// </summary>
- public void InsertLineBreak()
- {
- if (CurrentColumn > 0) {
- Insert (CurrentLine + 1, this [CurrentLine].Content.Substring (CurrentColumn));
- UpdateLine (CurrentLine, this [CurrentLine].Content.Substring (0, CurrentColumn));
- } else
- Insert(CurrentLine, "");
-
- CurrentColumn = 0;
- CurrentLine++;
- }
- #endregion
- }
-}
-
+++ /dev/null
-using System;
-
-namespace Crow.Coding
-{
- public class CodeBufferEventArgs : EventArgs {
- public int LineStart;
- public int LineCount;
-
- public CodeBufferEventArgs(int lineNumber) {
- LineStart = lineNumber;
- LineCount = 1;
- }
- public CodeBufferEventArgs(int lineStart, int lineCount) {
- LineStart = lineStart;
- LineCount = lineCount;
- }
- }
-
-}
-
+++ /dev/null
-using System;
-using System.Text;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Crow.Coding
-{
- public class CodeLine
- {
- public string Content;
- public List<Token> Tokens;
- public int EndingState = 0;
- public Node SyntacticNode;
- public ParserException exception;
-
- public CodeLine (string _content){
- Content = _content;
- Tokens = null;
- exception = null;
- }
-
- public char this[int i]
- {
- get { return Content[i]; }
- set {
- if (Content [i] == value)
- return;
- StringBuilder sb = new StringBuilder(Content);
- sb[i] = value;
- Content = sb.ToString();
- Tokens = null;
- //LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i));
- }
- }
- public bool IsFoldable { get { return SyntacticNode == null ? false :
- SyntacticNode.EndLine != SyntacticNode.StartLine && SyntacticNode.EndLine != null; } }
- public int FoldingLevel { get { return IsFoldable ? SyntacticNode.Level : 0; } }
- public bool IsFolded = false;
- public bool IsParsed {
- get { return Tokens != null; }
- }
- public string PrintableContent {
- get {
- return string.IsNullOrEmpty (Content) ? "" : Content.Replace ("\t", new String (' ', Interface.TabSize));
- }
- }
- public int PrintableLength {
- get {
- return PrintableContent.Length;
- }
- }
- public int Length {
- get {
- return string.IsNullOrEmpty (Content) ? 0 : Content.Length;
- }
- }
- public int FirstNonBlankTokIndex {
- get { return Tokens == null ? -1 : Tokens.FindIndex (tk=>tk.Type != BufferParser.TokenType.WhiteSpace); }
- }
-
- public void SetLineInError (ParserException ex) {
- Tokens = null;
- exception = ex;
- }
-
-// public static implicit operator string(CodeLine sl) {
-// return sl == null ? "" : sl.Content;
-// }
- public static implicit operator CodeLine(string s) {
- return new CodeLine(s);
- }
- public static bool operator ==(string s1, CodeLine s2)
- {
- return string.Equals (s1, s2.Content);
- }
- public static bool operator !=(string s1, CodeLine s2)
- {
- return !string.Equals (s1, s2.Content);
- }
- }
-}
-
+++ /dev/null
-using System;
-using System.Collections.Generic;
-
-namespace Crow.Coding
-{
- public class Node
- {
- public Node Parent;
- public string Name;
- public string Type;
- public CodeLine StartLine;
- public CodeLine EndLine;
- public Dictionary<string,string> Attributes = new Dictionary<string, string> ();
-
- public List<Node> Children = new List<Node>();
-
- public Node ()
- {
- }
-
- public void AddChild (Node child) {
- child.Parent = this;
- Children.Add (child);
- }
-
- public int Level {
- get { return Parent == null ? 1 : Parent.Level + 1; }
- }
-
- public override string ToString ()
- {
- return string.Format ("Name:{0}, Type:{1}\n\tparent:{2}", Name, Type, Parent);
- }
- }
-}
-
+++ /dev/null
-//
-// ScrollingTextBox.cs
-//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-using System;
-using System.Xml.Serialization;
-using System.ComponentModel;
-using System.Collections;
-using Cairo;
-using System.Text;
-using System.Collections.Generic;
-using System.Text.RegularExpressions;
-using System.Linq;
-using System.Diagnostics;
-using System.IO;
-using System.Threading;
-
-namespace Crow.Coding
-{
- /// <summary>
- /// Scrolling text box optimized for monospace fonts, for coding
- /// </summary>
- public class SourceEditor : Editor
- {
- #region CTOR
- public SourceEditor (): base()
- {
- formatting.Add ((int)XMLParser.TokenType.AttributeName, new TextFormatting (Color.Teal, Color.Transparent));
- formatting.Add ((int)XMLParser.TokenType.ElementName, new TextFormatting (Color.DarkBlue, Color.Transparent));
- formatting.Add ((int)XMLParser.TokenType.ElementStart, new TextFormatting (Color.Black, Color.Transparent));
- formatting.Add ((int)XMLParser.TokenType.ElementEnd, new TextFormatting (Color.Black, Color.Transparent));
- formatting.Add ((int)XMLParser.TokenType.ElementClosing, new TextFormatting (Color.Black, Color.Transparent));
-
- formatting.Add ((int)XMLParser.TokenType.AttributeValueOpening, new TextFormatting (Color.Carmine, Color.Transparent));
- formatting.Add ((int)XMLParser.TokenType.AttributeValueClosing, new TextFormatting (Color.Carmine, Color.Transparent));
- formatting.Add ((int)XMLParser.TokenType.AttributeValue, new TextFormatting (Color.TractorRed, Color.Transparent, false, true));
- formatting.Add ((int)XMLParser.TokenType.XMLDecl, new TextFormatting (Color.AoEnglish, Color.Transparent));
-
- formatting.Add ((int)BufferParser.TokenType.BlockComment, new TextFormatting (Color.Gray, Color.Transparent, false, true));
- formatting.Add ((int)BufferParser.TokenType.LineComment, new TextFormatting (Color.Gray, Color.Transparent, false, true));
- formatting.Add ((int)BufferParser.TokenType.OperatorOrPunctuation, new TextFormatting (Color.Black, Color.Transparent));
- //formatting.Add ((int)BufferParser.TokenType.Keyword, new TextFormatting (Color.DarkCyan, Color.Transparent));
-
- parsing.Add (".crow", "Crow.Coding.XMLParser");
- parsing.Add (".svg", "Crow.Coding.XMLParser");
- parsing.Add (".template", "Crow.Coding.XMLParser");
- parsing.Add (".cs", "Crow.Coding.CSharpParser");
- parsing.Add (".style", "Crow.Coding.StyleParser");
-
- buffer = new CodeBuffer ();
- buffer.LineUpadateEvent += Buffer_LineUpadateEvent;
- buffer.LineAdditionEvent += Buffer_LineAdditionEvent;;
- buffer.LineRemoveEvent += Buffer_LineRemoveEvent;
- buffer.BufferCleared += Buffer_BufferCleared;
- buffer.SelectionChanged += Buffer_SelectionChanged;
- buffer.PositionChanged += Buffer_PositionChanged;
- buffer.FoldingEvent += Buffer_FoldingEvent;
- buffer.Add (new CodeLine(""));
- }
- #endregion
-
- string oldSource = "";
- //save requested position on error, and try it on next move
- int requestedLine = 0, requestedCol = 0;
- volatile bool isDirty = false;
-
- const int leftMarginGap = 3;//gap between items in margin and text
- const int foldSize = 9;//folding rectangles size
- const int foldHSpace = 4;//folding level tabulation x
- int foldMargin { get { return parser == null ? 0 : parser.SyntacticTreeMaxDepth * foldHSpace; }}//folding margin size
-
- #region private and protected fields
- bool foldingEnabled = true;
- int leftMargin = 0; //margin used to display line numbers, folding errors,etc...
- int visibleLines = 1;
- int visibleColumns = 1;
- int firstPrintedLine = -1;
- int printedCurrentLine = 0;//Index of the currentline in the PrintedLines array
-
- CodeBuffer buffer;
- BufferParser parser;
- List<CodeLine> PrintedLines;//list of lines visible in the Editor depending on scrolling and folding
-
- Dictionary<int, TextFormatting> formatting = new Dictionary<int, TextFormatting>();
- Dictionary<string, string> parsing = new Dictionary<string, string>();
-
- Color selBackground;
- Color selForeground;
- int selStartCol;
- int selEndCol;
-
- protected Rectangle rText;
- protected FontExtents fe;
- protected TextExtents te;
-
- Point mouseLocalPos;
- bool doubleClicked = false;
- #endregion
-
- void measureLeftMargin () {
- leftMargin = 0;
- if (PrintLineNumbers)
- leftMargin += (int)Math.Ceiling((double)buffer.LineCount.ToString().Length * fe.MaxXAdvance) +6;
- if (foldingEnabled)
- leftMargin += foldMargin;
- if (leftMargin > 0)
- leftMargin += leftMarginGap;
- updateVisibleColumns ();
- }
- void findLongestLineAndUpdateMaxScrollX() {
- buffer.FindLongestVisualLine ();
- updateMaxScrollX ();
-// Debug.WriteLine ("SourceEditor: Find Longest line and update maxscrollx: {0} visible cols:{1}", MaxScrollX, visibleColumns);
- }
- /// <summary>
- /// Updates visible line in widget, adapt max scroll y and updatePrintedLines
- /// </summary>
- void updateVisibleLines(){
- visibleLines = (int)Math.Floor ((double)ClientRectangle.Height / (fe.Ascent+fe.Descent));
- NotifyValueChanged ("VisibleLines", visibleLines);
- updateMaxScrollY ();
- updatePrintedLines ();
- RegisterForGraphicUpdate ();
-// System.Diagnostics.Debug.WriteLine ("update visible lines: " + visibleLines);
-// System.Diagnostics.Debug.WriteLine ("update MaxScrollY: " + MaxScrollY);
- }
- void updateVisibleColumns(){
- visibleColumns = (int)Math.Floor ((double)(ClientRectangle.Width - leftMargin)/ fe.MaxXAdvance);
- NotifyValueChanged ("VisibleColumns", visibleColumns);
- updateMaxScrollX ();
-// System.Diagnostics.Debug.WriteLine ("update visible columns: {0} leftMargin:{1}",visibleColumns, leftMargin);
-// System.Diagnostics.Debug.WriteLine ("update MaxScrollX: " + MaxScrollX);
- }
- void updateMaxScrollX () {
- MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns);
- if (buffer.longestLineCharCount > 0)
- NotifyValueChanged ("ChildWidthRatio", Slot.Width * visibleColumns / buffer.longestLineCharCount);
- }
- void updateMaxScrollY () {
- if (parser == null || !foldingEnabled) {
- MaxScrollY = Math.Max (0, buffer.LineCount - visibleLines);
- if (buffer.UnfoldedLines > 0)
- NotifyValueChanged ("ChildHeightRatio", Slot.Height * visibleLines / buffer.UnfoldedLines);
- } else {
- MaxScrollY = Math.Max (0, buffer.UnfoldedLines - visibleLines);
- if (buffer.UnfoldedLines > 0)
- NotifyValueChanged ("ChildHeightRatio", Slot.Height * visibleLines / buffer.UnfoldedLines);
- }
- }
- void updatePrintedLines () {
- buffer.editMutex.EnterReadLock ();
- editorMutex.EnterWriteLock ();
-
- PrintedLines = new List<CodeLine> ();
- int curL = 0;
- int i = 0;
-
- while (curL < buffer.LineCount && i < ScrollY) {
- if (buffer [curL].IsFolded)
- curL = buffer.GetEndNodeIndex (curL);
- curL++;
- i++;
- }
-
- firstPrintedLine = curL;
- i = 0;
- while (i < visibleLines && curL < buffer.LineCount) {
- PrintedLines.Add (buffer [curL]);
-
- if (buffer [curL].IsFolded)
- curL = buffer.GetEndNodeIndex (curL);
-
- curL++;
- i++;
- }
-
- buffer.editMutex.ExitReadLock ();
- editorMutex.ExitWriteLock ();
- }
- void updateOnScreenCurLineFromBuffCurLine(){
- printedCurrentLine = PrintedLines.IndexOf (buffer.CurrentCodeLine);
- }
- void toogleFolding (int line) {
- if (parser == null || !foldingEnabled)
- return;
- buffer.ToogleFolding (line);
- }
-
- #region Editor overrides
- protected override void updateEditorFromProjFile ()
- {
- buffer.editMutex.EnterWriteLock ();
- loadSource ();
- buffer.editMutex.ExitWriteLock ();
-
- isDirty = false;
- oldSource = projFile.Source;
- CurrentLine = requestedLine;
- CurrentColumn = requestedCol;
- projFile.RegisteredEditors [this] = true;
- }
- protected override void updateProjFileFromEditor ()
- {
- buffer.editMutex.EnterWriteLock ();
- string newsrc = buffer.FullText;
- buffer.editMutex.ExitWriteLock ();
- projFile.UpdateSource (this, newsrc);
- }
- protected override bool EditorIsDirty {
- get { return isDirty; }
- set { isDirty = value; }
- }
- protected override bool IsReady {
- get { return buffer != null; }
- }
- #endregion
-
- #region Buffer events handlers
- void Buffer_BufferCleared (object sender, EventArgs e)
- {
- editorMutex.EnterWriteLock ();
-
- buffer.longestLineCharCount = 0;
- buffer.longestLineIdx = 0;
- measureLeftMargin ();
- MaxScrollX = MaxScrollY = 0;
- PrintedLines = null;
- RegisterForGraphicUpdate ();
- notifyPositionChanged ();
- isDirty = true;
-
- editorMutex.ExitWriteLock ();
- }
- void Buffer_LineAdditionEvent (object sender, CodeBufferEventArgs e)
- {
- for (int i = 0; i < e.LineCount; i++) {
- int lptr = e.LineStart + i;
- int charCount = buffer[lptr].PrintableLength;
- if (charCount > buffer.longestLineCharCount) {
- buffer.longestLineIdx = lptr;
- buffer.longestLineCharCount = charCount;
- }else if (lptr <= buffer.longestLineIdx)
- buffer.longestLineIdx++;
- if (parser == null)
- continue;
- parser.TryParseBufferLine (e.LineStart + i);
- }
-
- if (parser != null)
- parser.reparseSource ();
-
- measureLeftMargin ();
-
- updatePrintedLines ();
- updateMaxScrollY ();
- RegisterForGraphicUpdate ();
- notifyPositionChanged ();
- isDirty = true;
- }
- void Buffer_LineRemoveEvent (object sender, CodeBufferEventArgs e)
- {
- bool trigFindLongestLine = false;
- for (int i = 0; i < e.LineCount; i++) {
- int lptr = e.LineStart + i;
- if (lptr <= buffer.longestLineIdx)
- trigFindLongestLine = true;
- }
- if (trigFindLongestLine)
- findLongestLineAndUpdateMaxScrollX ();
-
- measureLeftMargin ();
- updatePrintedLines ();
- updateMaxScrollY ();
- RegisterForGraphicUpdate ();
- notifyPositionChanged ();
- isDirty = true;
- }
- void Buffer_LineUpadateEvent (object sender, CodeBufferEventArgs e)
- {
- bool trigFindLongestLine = false;
- for (int i = 0; i < e.LineCount; i++) {
-
- int lptr = e.LineStart + i;
- if (lptr == buffer.longestLineIdx)
- trigFindLongestLine = true;
- else if (buffer[lptr].PrintableLength > buffer.longestLineCharCount) {
- buffer.longestLineCharCount = buffer[lptr].PrintableLength;
- buffer.longestLineIdx = lptr;
- }
- }
- if (trigFindLongestLine)
- findLongestLineAndUpdateMaxScrollX ();
-
- RegisterForGraphicUpdate ();
- notifyPositionChanged ();
- isDirty = true;
- }
- void Buffer_PositionChanged (object sender, EventArgs e)
- {
- Console.WriteLine ("Position changes: ({0},{1})", buffer.CurrentLine, buffer.CurrentColumn);
- int cc = buffer.CurrentTabulatedColumn;
-
- if (cc > visibleColumns + ScrollX) {
- ScrollX = cc - visibleColumns;
- } else if (cc < ScrollX)
- ScrollX = cc;
-
- RegisterForGraphicUpdate ();
- updateOnScreenCurLineFromBuffCurLine ();
- notifyPositionChanged ();
- }
-
- void Buffer_SelectionChanged (object sender, EventArgs e)
- {
- RegisterForGraphicUpdate ();
- }
- void Buffer_FoldingEvent (object sender, CodeBufferEventArgs e)
- {
- updatePrintedLines ();
- updateOnScreenCurLineFromBuffCurLine ();
- updateMaxScrollY ();
- RegisterForGraphicUpdate ();
- }
- #endregion
-
- void notifyPositionChanged (){
- try {
- NotifyValueChanged ("CurrentLine", buffer.CurrentLine+1);
- NotifyValueChanged ("CurrentColumn", buffer.CurrentColumn+1);
- NotifyValueChanged ("CurrentLineHasError", CurrentLineHasError);
- NotifyValueChanged ("CurrentLineError", CurrentLineError);
- } catch (Exception ex) {
- Console.WriteLine (ex.ToString ());
- }
- }
-
- #region Public Crow Properties
- public int CurrentLine{
- get { return buffer == null ? 0 : buffer.CurrentLine+1; }
- set {
- try {
- int l = value - 1;
- if (l == buffer.CurrentLine)
- return;
- buffer.CurrentLine = l;
- if (buffer [l].IsFolded)
- buffer.ToogleFolding (l);
- } catch (Exception ex) {
- requestedLine = value - 1;
- Console.WriteLine ("Error cur column: " + ex.ToString ());
- }
- }
- }
- public int CurrentColumn{
- get { return buffer == null ? 0 : buffer.CurrentColumn+1; }
- set {
- try {
- if (value - 1 == buffer.CurrentColumn)
- return;
- buffer.CurrentColumn = value - 1;
- } catch (Exception ex) {
- requestedCol = value - 1;
- Console.WriteLine ("Error cur column: " + ex.ToString ());
- }
- }
- }
- public bool PrintLineNumbers
- {
- get { return Configuration.Global.Get<bool> ("PrintLineNumbers"); }
- set {
- if (PrintLineNumbers == value)
- return;
- Configuration.Global.Set ("PrintLineNumbers", value);
- NotifyValueChanged ("PrintLineNumbers", PrintLineNumbers);
- measureLeftMargin ();
- RegisterForGraphicUpdate ();
- }
- }
- [DefaultValue("BlueGray")]
- public virtual Color SelectionBackground {
- get { return selBackground; }
- set {
- if (value == selBackground)
- return;
- selBackground = value;
- NotifyValueChanged ("SelectionBackground", selBackground);
- RegisterForRedraw ();
- }
- }
- [DefaultValue("White")]
- public virtual Color SelectionForeground {
- get { return selForeground; }
- set {
- if (value == selForeground)
- return;
- selForeground = value;
- NotifyValueChanged ("SelectionForeground", selForeground);
- RegisterForRedraw ();
- }
- }
- public override int ScrollY {
- get {
- return base.ScrollY;
- }
- set {
- if (value == base.ScrollY)
- return;
- base.ScrollY = value;
- updatePrintedLines ();
- updateOnScreenCurLineFromBuffCurLine ();
- RegisterForGraphicUpdate ();
- }
- }
- public ParserException CurrentLineError {
- get { return buffer?.CurrentCodeLine?.exception; }
- }
- public bool CurrentLineHasError {
- get { return buffer == null ? false : buffer.CurrentCodeLine == null ? false :
- buffer.CurrentCodeLine.exception != null; }
- }
- public override ProjectFile ProjectNode {
- get {
- return base.ProjectNode;
- }
- set {
- base.ProjectNode = value;
- if (projFile != null)
- parser = getParserFromExt (System.IO.Path.GetExtension (projFile.Extension));
- }
- }
- #endregion
-
- BufferParser getParserFromExt (string extension) {
- if (string.IsNullOrEmpty(extension))
- return null;
- if (!parsing.ContainsKey(extension))
- return null;
- Type parserType = Type.GetType (parsing [extension]);
- if (parserType == null)
- return null;
- return (BufferParser)Activator.CreateInstance (parserType, buffer );
- }
- void loadSource () {
-
- try {
-
- if (parser == null)
- buffer.Load (projFile.Source);
- else//parser may have special linebrk rules
- buffer.Load (projFile.Source, parser.LineBrkRegex);
-
- } catch (Exception ex) {
- Debug.WriteLine (ex.ToString ());
- }
-
- projFile.RegisteredEditors [this] = true;
-
- updateMaxScrollY ();
- MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns);
- updatePrintedLines ();
-
- RegisterForGraphicUpdate ();
- }
-
- /// <summary>
- /// Current editor line, when set, update buffer.CurrentLine
- /// </summary>
- int PrintedCurrentLine {
- get { return printedCurrentLine;}
- set {
- if (value < 0) {
- ScrollY += value;
- printedCurrentLine = 0;
- } else if (PrintedLines.Count < visibleLines && value >= PrintedLines.Count) {
- printedCurrentLine = PrintedLines.Count - 1;
- }else if (value >= visibleLines) {
- ScrollY += value - visibleLines + 1;
- printedCurrentLine = visibleLines - 1;
- }else
- printedCurrentLine = value;
- //Debug.WriteLine ("printed current line:" + printedCurrentLine.ToString ());
- //update position in buffer
- buffer.CurrentLine = buffer.IndexOf (PrintedLines[printedCurrentLine]);
- }
- }
- int getTabulatedColumn (int col, int line) {
- return buffer [line].Content.Substring (0, col).Replace ("\t", new String (' ', Interface.TabSize)).Length;
- }
- int getTabulatedColumn (Point pos) {
- return getTabulatedColumn (pos.X,pos.Y);
- }
- /// <summary>
- /// Moves cursor one char to the left, move up if cursor reaches start of line
- /// </summary>
- /// <returns><c>true</c> if move succeed</returns>
- public bool MoveLeft(){
- if (buffer.CurrentColumn == 0) {
- if (printedCurrentLine == 0)
- return false;
- PrintedCurrentLine--;
- buffer.CurrentColumn = int.MaxValue;
- } else
- buffer.CurrentColumn--;
- return true;
- }
- /// <summary>
- /// Moves cursor one char to the right, move down if cursor reaches end of line
- /// </summary>
- /// <returns><c>true</c> if move succeed</returns>
- public bool MoveRight(){
- if (buffer.CurrentColumn >= buffer.CurrentCodeLine.Length) {
- if (PrintedCurrentLine == buffer.UnfoldedLines - 1)
- return false;
- buffer.CurrentColumn = 0;
- PrintedCurrentLine++;
- } else
- buffer.CurrentColumn++;
- return true;
- }
-
- #region Drawing
- void drawLine(Context gr, Rectangle cb, int i) {
- CodeLine cl = PrintedLines[i];
- int lineIndex = buffer.IndexOf(cl);
-
- double y = cb.Y + (fe.Ascent+fe.Descent) * i, x = cb.X;
-
- //Draw line numbering
- Color mgFg = Color.Gray;
- Color mgBg = Color.White;
- if (PrintLineNumbers){
- Rectangle mgR = new Rectangle ((int)x, (int)y, leftMargin - leftMarginGap, (int)Math.Ceiling((fe.Ascent+fe.Descent)));
- if (cl.exception != null) {
- mgBg = Color.Red;
- if (buffer.CurrentLine == lineIndex)
- mgFg = Color.White;
- else
- mgFg = Color.LightGray;
- }else if (buffer.CurrentLine == lineIndex) {
- mgFg = Color.Black;
- mgBg = Color.DarkGray;
- }
- string strLN = (lineIndex+1).ToString ();
- gr.SetSourceColor (mgBg);
- gr.Rectangle (mgR);
- gr.Fill();
- gr.SetSourceColor (mgFg);
-
- gr.MoveTo (cb.X + (int)(gr.TextExtents (buffer.LineCount.ToString()).Width - gr.TextExtents (strLN).Width), y + fe.Ascent);
- gr.ShowText (strLN);
- gr.Fill ();
- }
-
-
-
- //draw folding
- if (foldingEnabled){
-
- Rectangle rFld = new Rectangle (cb.X + leftMargin - leftMarginGap - foldMargin,
- (int)(y + (fe.Ascent + fe.Descent) / 2.0 - foldSize / 2.0), foldSize, foldSize);
-
- gr.SetSourceColor (Color.Black);
- gr.LineWidth = 1.0;
-
- int level = 0;
- bool closingNode = false;
-
- if (currentNode != null) {
- if (cl == currentNode.EndLine) {
- currentNode = currentNode.Parent;
- closingNode = true;
- }
- if (currentNode != null)
- level = currentNode.Level - 1;
- }
-
- for (int l = 0; l < level; l++) {
- gr.MoveTo (rFld.Center.X + 0.5, y);
- gr.LineTo (rFld.Center.X + 0.5, y + fe.Ascent + fe.Descent);
- rFld.Left += foldHSpace;
- }
- if (closingNode) {
- gr.MoveTo (rFld.Center.X + 0.5, y);
- gr.LineTo (rFld.Center.X + 0.5, y + fe.Ascent / 2 + 0.5);
- gr.LineTo (rFld.Center.X + 0.5 + foldSize / 2, y + fe.Ascent / 2 + 0.5);
- closingNode = false;
- }
- gr.SetDash (new double[]{ 1.5 },0.0);
- gr.SetSourceColor (Color.Gray);
- gr.Stroke ();
- gr.SetDash (new double[]{}, 0.0);
-
- if (cl.IsFoldable) {
- gr.Rectangle (rFld);
- gr.SetSourceColor (Color.White);
- gr.Fill();
- gr.SetSourceColor (Color.Black);
- gr.Rectangle (rFld, 1.0);
- if (cl.IsFolded) {
- gr.MoveTo (rFld.Center.X + 0.5, rFld.Y + 2);
- gr.LineTo (rFld.Center.X + 0.5, rFld.Bottom - 2);
- }else
- currentNode = cl.SyntacticNode;
-
- gr.MoveTo (rFld.Left + 2, rFld.Center.Y + 0.5);
- gr.LineTo (rFld.Right - 2, rFld.Center.Y + 0.5);
- gr.Stroke ();
- }
- }
-
- gr.SetSourceColor (Foreground);
- x += leftMargin;
-
- if (cl.Tokens == null)
- drawRawCodeLine (gr, x, y, i, lineIndex);
- else
- drawParsedCodeLine (gr, x, y, i, lineIndex);
- }
- Node currentNode = null;
-// void drawParsed(Context gr){
-// if (PrintedLines == null)
-// return;
-//
-// gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
-// gr.SetFontSize (Font.Size);
-// gr.FontOptions = Interface.FontRenderingOptions;
-// gr.Antialias = Interface.Antialias;
-//
-// Rectangle cb = ClientRectangle;
-// gr.Save ();
-// CairoHelpers.CairoRectangle (gr, cb, CornerRadius);
-// gr.Clip ();
-//
-// bool selectionInProgress = false;
-//
-// Foreground.SetAsSource (gr);
-//
-// #region draw text cursor
-// if (SelBegin != SelRelease)
-// selectionInProgress = true;
-// else if (HasFocus){
-// gr.LineWidth = 1.0;
-// double cursorX = + leftMargin + cb.X + (CurrentColumn - ScrollX) * fe.MaxXAdvance;
-// gr.MoveTo (0.5 + cursorX, cb.Y + printedCurrentLine * (fe.Ascent+fe.Descent));
-// gr.LineTo (0.5 + cursorX, cb.Y + (printedCurrentLine + 1) * (fe.Ascent+fe.Descent));
-// gr.Stroke();
-// }
-// #endregion
-//
-// for (int i = 0; i < PrintedLines.Count; i++)
-// drawTokenLine (gr, i, selectionInProgress, cb);
-//
-// gr.Restore ();
-// }
- void drawRawCodeLine(Context gr, double x, double y, int i, int lineIndex) {
- string lstr = buffer[lineIndex].PrintableContent;
- if (ScrollX < lstr.Length)
- lstr = lstr.Substring (ScrollX);
- else
- lstr = "";
-
- gr.MoveTo (x, y + fe.Ascent);
- gr.ShowText (lstr);
- gr.Fill ();
-
- if (!buffer.SelectionIsEmpty && lineIndex >= buffer.SelectionStart.Y && lineIndex <= buffer.SelectionEnd.Y) {
- double rLineX = x,
- rLineY = y,
- rLineW = lstr.Length * fe.MaxXAdvance;
-
- //System.Diagnostics.Debug.WriteLine ("sel start: " + buffer.SelectionStart + " sel end: " + buffer.SelectionEnd);
- if (lineIndex == buffer.SelectionStart.Y) {
- rLineX += (selStartCol - ScrollX) * fe.MaxXAdvance;
- rLineW -= selStartCol * fe.MaxXAdvance;
- }
- if (lineIndex == buffer.SelectionEnd.Y)
- rLineW -= (lstr.Length - selEndCol) * fe.MaxXAdvance;
-
- gr.Save ();
- gr.Operator = Operator.Source;
- gr.Rectangle (rLineX, rLineY, rLineW, (fe.Ascent+fe.Descent));
- gr.SetSourceColor (SelectionBackground);
- gr.FillPreserve ();
- gr.Clip ();
- gr.Operator = Operator.Over;
- gr.SetSourceColor (SelectionForeground);
- gr.MoveTo (x, y + fe.Ascent);
- gr.ShowText (lstr);
- gr.Fill ();
- gr.Restore ();
- }
- }
- void drawParsedCodeLine (Context gr, double x, double y, int i, int lineIndex) {
- int lPtr = 0;
- CodeLine cl = PrintedLines[i];
-
- for (int t = 0; t < cl.Tokens.Count; t++) {
- string lstr = cl.Tokens [t].PrintableContent;
- if (lPtr < ScrollX) {
- if (lPtr - ScrollX + lstr.Length <= 0) {
- lPtr += lstr.Length;
- continue;
- }
- lstr = lstr.Substring (ScrollX - lPtr);
- lPtr += ScrollX - lPtr;
- }
- Color bg = this.Background;
- Color fg = this.Foreground;
- Color selbg = this.SelectionBackground;
- Color selfg = this.SelectionForeground;
- FontSlant fts = FontSlant.Normal;
- FontWeight ftw = FontWeight.Normal;
-
- if (formatting.ContainsKey ((int)cl.Tokens [t].Type)) {
- TextFormatting tf = formatting [(int)cl.Tokens [t].Type];
- bg = tf.Background;
- fg = tf.Foreground;
- if (tf.Bold)
- ftw = FontWeight.Bold;
- if (tf.Italic)
- fts = FontSlant.Italic;
- }
-
- gr.SelectFontFace (Font.Name, fts, ftw);
- gr.SetSourceColor (fg);
-
- gr.MoveTo (x, y + fe.Ascent);
- gr.ShowText (lstr);
- gr.Fill ();
-
- if (buffer.SelectionInProgress && lineIndex >= buffer.SelectionStart.Y && lineIndex <= buffer.SelectionEnd.Y &&
- !(lineIndex == buffer.SelectionStart.Y && lPtr + lstr.Length <= selStartCol) &&
- !(lineIndex == buffer.SelectionEnd.Y && selEndCol <= lPtr)) {
-
- double rLineX = x,
- rLineY = y,
- rLineW = lstr.Length * fe.MaxXAdvance;
- double startAdjust = 0.0;
-
- if ((lineIndex == buffer.SelectionStart.Y) && (selStartCol < lPtr + lstr.Length) && (selStartCol > lPtr))
- startAdjust = (selStartCol - lPtr) * fe.MaxXAdvance;
- rLineX += startAdjust;
- if ((lineIndex == buffer.SelectionEnd.Y) && (selEndCol < lPtr + lstr.Length))
- rLineW = (selEndCol - lPtr) * fe.MaxXAdvance;
- rLineW -= startAdjust;
-
- gr.Save ();
- gr.Operator = Operator.Source;
- gr.Rectangle (rLineX, rLineY, rLineW, (fe.Ascent+fe.Descent));
- gr.SetSourceColor (selbg);
- gr.FillPreserve ();
- gr.Clip ();
- gr.Operator = Operator.Over;
- gr.SetSourceColor (selfg);
- gr.MoveTo (x, y + fe.Ascent);
- gr.ShowText (lstr);
- gr.Fill ();
- gr.Restore ();
- }
- x += (int)lstr.Length * fe.MaxXAdvance;
- lPtr += lstr.Length;
- }
- }
-
- #endregion
-
- #region GraphicObject overrides
- public override Font Font {
- get { return base.Font; }
- set {
- base.Font = value;
-
- using (ImageSurface img = new ImageSurface (Format.Argb32, 1, 1)) {
- using (Context gr = new Context (img)) {
- gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
- gr.SetFontSize (Font.Size);
-
- fe = gr.FontExtents;
- }
- }
- MaxScrollY = 0;
- RegisterForGraphicUpdate ();
- }
- }
- protected override int measureRawSize(LayoutingType lt)
- {
- if (lt == LayoutingType.Height)
- return (int)Math.Ceiling((fe.Ascent+fe.Descent) * buffer.LineCount) + Margin * 2;
-
- return (int)(fe.MaxXAdvance * buffer.longestLineCharCount) + Margin * 2 + leftMargin;
- }
- public override void OnLayoutChanges (LayoutingType layoutType)
- {
- base.OnLayoutChanges (layoutType);
-
- if (layoutType == LayoutingType.Height)
- updateVisibleLines ();
- else if (layoutType == LayoutingType.Width)
- updateVisibleColumns ();
- }
-
- protected override void onDraw (Context gr)
- {
- base.onDraw (gr);
-
- gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
- gr.SetFontSize (Font.Size);
- gr.FontOptions = Interface.FontRenderingOptions;
- gr.Antialias = Interface.Antialias;
-
- Rectangle cb = ClientRectangle;
-
- Foreground.SetAsSource (gr);
-
- buffer.editMutex.EnterReadLock ();
- editorMutex.EnterReadLock ();
-
- #region draw text cursor
- if (buffer.SelectionInProgress){
- selStartCol = getTabulatedColumn (buffer.SelectionStart);
- selEndCol = getTabulatedColumn (buffer.SelectionEnd);
- }else if (HasFocus && printedCurrentLine >= 0){
- gr.LineWidth = 1.0;
- double cursorX = cb.X + (getTabulatedColumn(buffer.CurrentPosition) - ScrollX) * fe.MaxXAdvance + leftMargin;
- gr.MoveTo (0.5 + cursorX, cb.Y + (printedCurrentLine) * (fe.Ascent+fe.Descent));
- gr.LineTo (0.5 + cursorX, cb.Y + (printedCurrentLine + 1) * (fe.Ascent+fe.Descent));
- gr.Stroke();
- }
- #endregion
-
- if (PrintedLines != null) {
- int unfoldedLines = buffer.UnfoldedLines;
- currentNode = null;
- CodeLine cl = PrintedLines[0];
- int idx0 = buffer.IndexOf(cl);
- int li = idx0-1;
- while (li >= 0) {
- if (buffer [li].IsFoldable && !buffer [li].IsFolded) {
- if (buffer.IndexOf(buffer [li].SyntacticNode.EndLine) > idx0){
- currentNode = buffer [li].SyntacticNode;
- break;
- }
- }
- li--;
- }
-
- for (int i = 0; i < visibleLines; i++) {
- if (i + ScrollY >= unfoldedLines)//TODO:need optimize
- break;
- drawLine (gr, cb, i);
- }
- }
-
- editorMutex.ExitReadLock ();
-
- buffer.editMutex.ExitReadLock ();
-
- }
- #endregion
-
- #region Mouse handling
-
- int hoverLine = -1;
- public int HoverLine {
- get { return hoverLine; }
- set {
- if (hoverLine == value)
- return;
- hoverLine = value;
- NotifyValueChanged ("HoverLine", hoverLine);
- }
- }
- void updateHoverLine () {
- int hvl = (int)Math.Max (0, Math.Floor (mouseLocalPos.Y / (fe.Ascent+fe.Descent)));
- hvl = Math.Min (PrintedLines.Count, hvl);
- HoverLine = buffer.IndexOf (PrintedLines[hvl]);
- }
- void updateCurrentPosFromMouseLocalPos(){
- PrintedCurrentLine = (int)Math.Max (0, Math.Floor (mouseLocalPos.Y / (fe.Ascent+fe.Descent)));
- int curVisualCol = ScrollX + (int)Math.Round ((mouseLocalPos.X - leftMargin) / fe.MaxXAdvance);
-
- int i = 0;
- int buffCol = 0;
- while (i < curVisualCol && buffCol < buffer.CurrentCodeLine.Length) {
- if (buffer.CurrentCodeLine[buffCol] == '\t')
- i += Interface.TabSize;
- else
- i++;
- buffCol++;
- }
- buffer.CurrentColumn = buffCol;
- }
- public override void onMouseEnter (object sender, MouseMoveEventArgs e)
- {
- base.onMouseEnter (sender, e);
- if (e.X - ScreenCoordinates(Slot).X < leftMargin + ClientRectangle.X)
- IFace.MouseCursor = XCursor.Default;
- else
- IFace.MouseCursor = XCursor.Text;
- }
- public override void onMouseLeave (object sender, MouseMoveEventArgs e)
- {
- base.onMouseLeave (sender, e);
- IFace.MouseCursor = XCursor.Default;
- }
- public override void onMouseMove (object sender, MouseMoveEventArgs e)
- {
- base.onMouseMove (sender, e);
-
- mouseLocalPos = e.Position - ScreenCoordinates(Slot).TopLeft - ClientRectangle.TopLeft;
-
- updateHoverLine ();
-
- if (!e.Mouse.IsButtonDown (MouseButton.Left)) {
- if (mouseLocalPos.X < leftMargin)
- IFace.MouseCursor = XCursor.Default;
- else
- IFace.MouseCursor = XCursor.Text;
- return;
- }
-
- if (!HasFocus || !buffer.SelectionInProgress)
- return;
-
- //mouse is down
- updateCurrentPosFromMouseLocalPos();
- buffer.SetSelEndPos ();
- }
- public override void onMouseDown (object sender, MouseButtonEventArgs e)
- {
- if (!this.Focusable)
- return;
-
- if (mouseLocalPos.X >= leftMargin)
- base.onMouseDown (sender, e);
-
- if (doubleClicked) {
- doubleClicked = false;
- return;
- }
-
- if (mouseLocalPos.X < leftMargin) {
- toogleFolding (buffer.IndexOf (PrintedLines [(int)Math.Max (0, Math.Floor (mouseLocalPos.Y / (fe.Ascent+fe.Descent)))]));
- return;
- }
-
- updateCurrentPosFromMouseLocalPos ();
- buffer.SetSelStartPos ();
- }
- public override void onMouseUp (object sender, MouseButtonEventArgs e)
- {
- base.onMouseUp (sender, e);
-
- if (buffer.SelectionIsEmpty)
- buffer.ResetSelection ();
- }
-
- public override void onMouseDoubleClick (object sender, MouseButtonEventArgs e)
- {
- doubleClicked = true;
- base.onMouseDoubleClick (sender, e);
-
- buffer.GotoWordStart ();
- buffer.SetSelStartPos ();
- buffer.GotoWordEnd ();
- buffer.SetSelEndPos ();
- }
-
- public override void onMouseWheel (object sender, MouseWheelEventArgs e)
- {
- base.onMouseWheel (sender, e);
- }
- #endregion
-
- #region Keyboard handling
- public override void onKeyDown (object sender, KeyboardKeyEventArgs e)
- {
- //base.onKeyDown (sender, e);
-
- Key key = e.Key;
-
- if (e.Control) {
- switch (key) {
- case Key.S:
- projFile.Save ();
- break;
- case Key.W:
- editorMutex.EnterWriteLock ();
- if (e.Shift)
- projFile.Redo (null);
- else
- projFile.Undo (null);
- editorMutex.ExitWriteLock ();
- break;
- default:
- Console.WriteLine ("");
- break;
- }
- }
-
- switch (key)
- {
- case Key.Back:
- buffer.DeleteChar ();
- break;
- case Key.Clear:
- break;
- case Key.Delete:
- if (buffer.SelectionIsEmpty)
- MoveRight ();
- else if (e.Shift)
- IFace.Clipboard = buffer.SelectedText;
- buffer.DeleteChar ();
- break;
- case Key.Enter:
- case Key.KeypadEnter:
- if (!buffer.SelectionIsEmpty)
- buffer.DeleteChar ();
- buffer.InsertLineBreak ();
- break;
- case Key.Escape:
- buffer.ResetSelection ();
- break;
- case Key.Home:
- if (e.Shift) {
- if (buffer.SelectionIsEmpty)
- buffer.SetSelStartPos ();
- if (e.Control)
- buffer.CurrentLine = 0;
- buffer.CurrentColumn = 0;
- buffer.SetSelEndPos ();
- break;
- }
- buffer.ResetSelection ();
- if (e.Control)
- buffer.CurrentLine = 0;
- buffer.CurrentColumn = 0;
- break;
- case Key.End:
- if (e.Shift) {
- if (buffer.SelectionIsEmpty)
- buffer.SetSelStartPos ();
- if (e.Control)
- buffer.CurrentLine = int.MaxValue;
- buffer.CurrentColumn = int.MaxValue;
- buffer.SetSelEndPos ();
- break;
- }
- buffer.ResetSelection ();
- if (e.Control)
- buffer.CurrentLine = int.MaxValue;
- buffer.CurrentColumn = int.MaxValue;
- break;
- case Key.Insert:
- if (e.Shift)
- buffer.Insert (IFace.Clipboard);
- else if (e.Control && !buffer.SelectionIsEmpty)
- IFace.Clipboard = buffer.SelectedText;
- break;
- case Key.Left:
- if (e.Shift) {
- if (buffer.SelectionIsEmpty)
- buffer.SetSelStartPos ();
- if (e.Control)
- buffer.GotoWordStart ();
- else
- MoveLeft ();
- buffer.SetSelEndPos ();
- break;
- }
- buffer.ResetSelection ();
- if (e.Control)
- buffer.GotoWordStart ();
- else
- MoveLeft();
- break;
- case Key.Right:
- if (e.Shift) {
- if (buffer.SelectionIsEmpty)
- buffer.SetSelStartPos ();
- if (e.Control)
- buffer.GotoWordEnd ();
- else
- MoveRight ();
- buffer.SetSelEndPos ();
- break;
- }
- buffer.ResetSelection ();
- if (e.Control)
- buffer.GotoWordEnd ();
- else
- MoveRight ();
- break;
- case Key.Up:
- if (e.Shift) {
- if (buffer.SelectionIsEmpty)
- buffer.SetSelStartPos ();
- PrintedCurrentLine--;
- buffer.SetSelEndPos ();
- break;
- }
- buffer.ResetSelection ();
- PrintedCurrentLine--;
- break;
- case Key.Down:
- if (e.Shift) {
- if (buffer.SelectionIsEmpty)
- buffer.SetSelStartPos ();
- PrintedCurrentLine++;
- buffer.SetSelEndPos ();
- break;
- }
- buffer.ResetSelection ();
- PrintedCurrentLine++;
- break;
- case Key.Menu:
- break;
- case Key.NumLock:
- break;
- case Key.PageDown:
- if (e.Shift) {
- if (buffer.SelectionIsEmpty)
- buffer.SetSelStartPos ();
- PrintedCurrentLine += visibleLines;
- buffer.SetSelEndPos ();
- break;
- }
- buffer.ResetSelection ();
- PrintedCurrentLine += visibleLines;
- break;
- case Key.PageUp:
- if (e.Shift) {
- if (buffer.SelectionIsEmpty)
- buffer.SetSelStartPos ();
- PrintedCurrentLine -= visibleLines;
- buffer.SetSelEndPos ();
- break;
- }
- buffer.ResetSelection ();
- PrintedCurrentLine -= visibleLines;
- break;
- case Key.RWin:
- break;
- case Key.Tab:
- if (e.Shift) {
- if (buffer.SelectionIsEmpty ||
- (buffer.SelectionStart.Y == buffer.SelectionEnd.Y)) {
- //TODO
- break;
- }
- for (int i = buffer.SelectionStart.Y; i <= buffer.SelectionEnd.Y; i++)
- buffer.RemoveLeadingTab (i);
- buffer.SetSelectionOnFullLines ();
- } else {
- if (buffer.SelectionIsEmpty ||
- (buffer.SelectionStart.Y == buffer.SelectionEnd.Y)) {
- buffer.Insert ("\t");
- break;
- }
- for (int i = buffer.SelectionStart.Y; i <= buffer.SelectionEnd.Y; i++) {
- buffer.UpdateLine (i, "\t" + buffer [i].Content);
- }
- }
-
- break;
- case Key.F8:
- toogleFolding (buffer.CurrentLine);
- break;
- default:
- break;
- }
- RegisterForGraphicUpdate();
- }
- public override void onKeyPress (object sender, KeyPressEventArgs e)
- {
- base.onKeyPress (sender, e);
-
- buffer.Insert (e.KeyChar.ToString());
- buffer.ResetSelection ();
- }
- #endregion
- }
-}
\ No newline at end of file
+++ /dev/null
-using System;
-using Crow;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Text.RegularExpressions;
-using System.Linq;
-
-namespace Crow.Coding
-{
- public class StyleParser : BufferParser
- {
- enum States { init, classNames, members, value, endOfStatement }
-
- public StyleParser (CodeBuffer _buffer) : base(_buffer)
- {
- }
-
- #region Character ValidityCheck
- static Regex rxValidChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}");
- static Regex rxNameStartChar = new Regex(@"_|\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}");
- static Regex rxNameChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}");
- static Regex rxDecimal = new Regex(@"[0-9]+");
- static Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+");
-
- public bool nextCharIsValidCharStartName
- {
- get { return rxNameStartChar.IsMatch(new string(new char[]{Peek()})); }
- }
- public bool nextCharIsValidCharName
- {
- get { return rxNameChar.IsMatch(new string(new char[]{Peek()})); }
- }
- #endregion
-
- States curState = States.classNames;
-
- public override void ParseCurrentLine ()
- {
- //Debug.WriteLine (string.Format("parsing line:{0}", currentLine));
- CodeLine cl = buffer [currentLine];
- cl.Tokens = new List<Token> ();
-
- //retrieve current parser state from previous line
- if (currentLine > 0)
- curState = (States)buffer[currentLine - 1].EndingState;
- else
- curState = States.init;
-
- States previousEndingState = (States)cl.EndingState;
-
- while (! eol) {
- SkipWhiteSpaces ();
-
- if (eol)
- break;
-
- if (Peek () == '\n') {
- if (currentTok != TokenType.Unknown)
- throw new ParserException (currentLine, currentColumn, "Unexpected end of line");
- Read ();
- eol = true;
- continue;
- }
-
- switch (Peek()) {
- case '/':
- readToCurrTok (true);
- switch (Peek ()) {
- case '/':
- currentTok += ReadLine ();
- saveAndResetCurrentTok (TokenType.LineComment);
- break;
- default:
- currentTok += ReadLine ();
- saveAndResetCurrentTok (TokenType.Unknown);
- break;
- }
- break;
- case ',':
- if (curState != States.init && curState != States.classNames )
- throw new ParserException (currentLine, currentColumn, "Unexpected char ','");
- readAndResetCurrentTok (TokenType.OperatorOrPunctuation, true);
- curState = States.classNames;
- break;
- case '{':
- if (!(curState == States.init || curState == States.classNames))
- throw new ParserException (currentLine, currentColumn, "Unexpected char '{'");
- readAndResetCurrentTok (TokenType.OpenBlock, true);
- curState = States.members;
- break;
- case '}':
- if (curState != States.members)
- throw new ParserException (currentLine, currentColumn, "Unexpected char '}'");
- readAndResetCurrentTok (TokenType.CloseBlock, true);
- curState = States.classNames;
- break;
- case '=':
- if (curState == States.classNames)
- throw new ParserException (currentLine, currentColumn, "Unexpected char '='");
- setPreviousTokOfTypeTo (TokenType.Type, TokenType.Identifier);
- readAndResetCurrentTok (TokenType.OperatorOrPunctuation, true);
- curState = States.value;
- break;
- case '"':
- if (curState != States.value)
- throw new ParserException (currentLine, currentColumn, "Unexpected char '\"'");
- readAndResetCurrentTok (TokenType.StringLitteralOpening, true);
-
- while (!eol) {
- currentTok += ReadLineUntil ("\"");
- if (currentTok.Content [currentTok.Content.Length - 1] == '\\')
- readToCurrTok ();
- else
- break;
- }
- if (eol)
- throw new ParserException (currentLine, currentColumn, "Unexpected end of line");
- saveAndResetCurrentTok (TokenType.StringLitteral);
-
- readAndResetCurrentTok (TokenType.StringLitteralClosing, true);
- curState = States.endOfStatement;
- break;
- case ';':
- if (curState != States.endOfStatement)
- throw new ParserException (currentLine, currentColumn, "Unexpected end of statement");
- readAndResetCurrentTok (TokenType.StatementEnding, true);
- curState = States.members;
- break;
- default:
- if (currentTok.Type != TokenType.Unknown)
- throw new ParserException (currentLine, currentColumn, "error curtok not null");
- if (curState == States.value)
- throw new ParserException (currentLine, currentColumn, "expecting value enclosed in '\"'");
- if (curState == States.endOfStatement)
- throw new ParserException (currentLine, currentColumn, "expecting end of statement");
-
- if (nextCharIsValidCharStartName) {
- readToCurrTok (true);
- while (nextCharIsValidCharName)
- readToCurrTok ();
- }
- saveAndResetCurrentTok (TokenType.Type);
- break;
- }
- }
-
- if (cl.EndingState != (int)curState && currentLine < buffer.LineCount - 1)
- buffer [currentLine + 1].Tokens = null;
-
- cl.EndingState = (int)curState;
- }
- public override void SyntaxAnalysis ()
- {
- initSyntaxAnalysis ();
- Node currentNode = RootNode;
-
- for (int i = 0; i < buffer.LineCount; i++) {
- CodeLine cl = buffer[i];
- if (cl.Tokens == null)
- continue;
- cl.SyntacticNode = null;
-
- int tokPtr = 0;
- while (tokPtr < cl.Tokens.Count) {
- switch (cl.Tokens [tokPtr].Type) {
- case TokenType.OpenBlock:
- currentNode = addChildNode (currentNode, cl, tokPtr, "style");
- break;
- case TokenType.CloseBlock:
- closeNodeAndGoUp (ref currentNode, cl, "style");
- break;
- }
- tokPtr++;
- }
- }
- }
- }
-}
-
+++ /dev/null
-using System;
-
-namespace Crow.Coding
-{
- public struct TextFormatting {
- public Color Foreground;
- public Color Background;
- public bool Bold;
- public bool Italic;
-
- public TextFormatting(Color fg, Color bg, bool bold = false, bool italic = false){
- Foreground = fg;
- Background = bg;
- Bold = bold;
- Italic = italic;
- }
- }
-}
-
+++ /dev/null
-//
-// Token.cs
-//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2017 jp
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-using System;
-
-namespace Crow.Coding
-{
- public struct Token
- {
- public BufferParser.TokenType Type;
- public string Content;
- public Point Start;
- public Point End;
-
- public string PrintableContent {
- get { return string.IsNullOrEmpty(Content) ? "" : Content.Replace("\t", new String(' ', Interface.TabSize)); }
- }
-
-// public Token (TokenType tokType, string content = ""){
-// Type = tokType;
-// Content = content;
-// }
-
- public bool IsNull { get { return IsEmpty && Type == BufferParser.TokenType.Unknown; }}
- public bool IsEmpty { get { return string.IsNullOrEmpty(Content); }}
-
- public static bool operator == (Token t, System.Enum tt){
- return Convert.ToInt32(t.Type) == Convert.ToInt32(tt);
- }
- public static bool operator != (Token t, System.Enum tt){
- return Convert.ToInt32(t.Type) != Convert.ToInt32(tt);
- }
- public static bool operator == (System.Enum tt, Token t){
- return Convert.ToInt32(t.Type) == Convert.ToInt32(tt);
- }
- public static bool operator != (System.Enum tt, Token t){
- return Convert.ToInt32(t.Type) != Convert.ToInt32(tt);
- }
-
- public static Token operator +(Token t, char c){
- t.Content += c;
- return t;
- }
- public static Token operator +(Token t, string s){
- t.Content += s;
- return t;
- }
- public override string ToString ()
- {
- return string.Format ("[Tok{2}->{3}:{0}: {1}]", Type,Content,Start,End);
- }
- }
-}
-
+++ /dev/null
-using System;
-using Crow;
-using System.Collections.Generic;
-using System.Text.RegularExpressions;
-using System.Diagnostics;
-using System.Linq;
-
-namespace Crow.Coding
-{
- public class XMLParser : BufferParser
- {
- public new enum TokenType {
- Unknown = BufferParser.TokenType.Unknown,
- WhiteSpace = BufferParser.TokenType.WhiteSpace,
- NewLine = BufferParser.TokenType.NewLine,
- LineComment = BufferParser.TokenType.LineComment,
- BlockCommentStart = BufferParser.TokenType.BlockCommentStart,
- BlockComment = BufferParser.TokenType.BlockComment,
- BlockCommentEnd = BufferParser.TokenType.BlockCommentEnd,
- ElementName = BufferParser.TokenType.Identifier,
- AttributeName = BufferParser.TokenType.Keyword,
- ElementClosing = BufferParser.TokenType.StatementEnding,
- Affectation = BufferParser.TokenType.OperatorOrPunctuation,
- AttributeValueOpening = BufferParser.TokenType.StringLitteralOpening,
- AttributeValueClosing = BufferParser.TokenType.StringLitteralClosing,
- AttributeValue = BufferParser.TokenType.StringLitteral,
- XMLDecl = BufferParser.TokenType.Preprocessor,
- ElementStart = 50,
- ElementEnd = 51,
- }
-
- public enum States
- {
- init, //first statement of prolog, xmldecl should only apear in this state
- prolog, //misc before doctypedecl
- InternalSubset, //doctype declaration subset
- ExternalSubsetInit,
- ExternalSubset,
- BlockComment,
- DTDEnd,//doctype finished
- XML,//normal xml
- StartTag,//inside start tag
- Content,//after start tag with no closing slash
- EndTag
- }
-
- #region CTOR
- public XMLParser (CodeBuffer _buffer) : base(_buffer) {}
- #endregion
-
- enum Keywords
- {
- DOCTYPE,
- ELEMENT,
- ATTLIST,
- ENTITY,
- NOTATION
- }
-
- States curState = States.init;
-
- #region Regular Expression for validity checks
- //private static Regex rxValidChar = new Regex("[\u0020-\uD7FF]");
- private static Regex rxValidChar = new Regex(@"\u0009|\u000A|\u000D|[\u0020-\uD7FF]|[\uE000-\uFFFD]"); //| [\u10000-\u10FFFF] unable to set those plans
- private static Regex rxNameStartChar = new Regex(@":|[A-Z]|_|[a-z]|[\u00C0-\u00D6]|[\u00D8-\u00F6]|[\u00F8-\u02FF]|[\u0370-\u037D]|[\u037F-\u1FFF]|[\u200C-\u200D]|[\u2070-\u218F]|[\u2C00-\u2FEF]|[\u3001-\uD7FF]|[\uF900-\uFDCF]|[\uFDF0-\uFFFD]"); // | [\u10000-\uEFFFF]
- private static Regex rxNameChar = new Regex(@":|[A-Z]|_|[a-z]|[\u00C0-\u00D6]|[\u00D8-\u00F6]|[\u00F8-\u02FF]|[\u0370-\u037D]|[\u037F-\u1FFF]|[\u200C-\u200D]|[\u2070-\u218F]|[\u2C00-\u2FEF]|[\u3001-\uD7FF]|[\uF900-\uFDCF]|[\uFDF0-\uFFFD]|-|\.|[0-9]|\u00B7|[\u0300-\u036F]|[\u203F-\u2040]");//[\u10000-\uEFFFF]|
- private static Regex rxDecimal = new Regex(@"[0-9]+");
- private static Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+");
- private static Regex rxAttributeValue = new Regex(@"[^<]");
- private static Regex rxEntityValue = new Regex(@"[^<]");
- private static Regex rxPubidChar = new Regex(@"\u0020|\u000D|\u000A|[a-zA-Z0-9]|[-\(\)\+\,\./:=\?;!\*#@\$_%]");
- #endregion
-
- #region Character ValidityCheck
- public bool nextCharIsValidCharStartName
- {
- get { return rxNameStartChar.IsMatch(new string(new char[]{Peek()})); }
- }
- public bool nextCharIsValidCharName
- {
- get { return rxNameChar.IsMatch(new string(new char[]{Peek()})); }
- }
- #endregion
-
- public override void SetLineInError (ParserException ex)
- {
- base.SetLineInError (ex);
- //buffer[ex.Line].Tokens.EndingState = (int)States.init;
- }
-
- public override void ParseCurrentLine ()
- {
- //Debug.WriteLine (string.Format("parsing line:{0}", currentLine));
- CodeLine cl = buffer [currentLine];
- cl.Tokens = new List<Token> ();
-
- //retrieve current parser state from previous line
- if (currentLine > 0)
- curState = (States)buffer[currentLine - 1].EndingState;
- else
- curState = States.init;
-
- States previousEndingState = (States)cl.EndingState;
-
-
- while (! eol) {
- SkipWhiteSpaces ();
-
- if (eol)
- break;
-
- if (Peek () == '\n') {
- if (currentTok != TokenType.Unknown)
- throw new ParserException (currentLine, currentColumn, "Unexpected end of line");
- Read ();
- eol = true;
- continue;
- }
-
- if (curState == States.BlockComment) {
- if (currentTok != TokenType.Unknown)
- Debugger.Break ();
-
- currentTok.Start = CurrentPosition;
- currentTok.Type = (BufferParser.TokenType)TokenType.BlockComment;
- currentTok += ReadLineUntil ("-->");
- if (Peek (3) == "-->") {
- readToCurrTok (3);
- curState = States.XML;
- }
- saveAndResetCurrentTok ();
- continue;
- }
-
- switch (Peek()) {
- case '<':
- readToCurrTok (true);
- switch (Peek()) {
- case '?':
- if (curState != States.init)
- throw new ParserException (currentLine, currentColumn, "xml decl may appear only on first line");
- readToCurrTok ();
- currentTok += ReadLineUntil ("?>");
- if (Peek (2) != "?>")
- throw new ParserException (currentLine, currentColumn, "expecting '?>'");
- readToCurrTok (2);
- saveAndResetCurrentTok (TokenType.XMLDecl);
- curState = States.prolog;
- break;
- case '!':
- readToCurrTok ();
- switch (Peek()) {
- case '-':
- readToCurrTok ();
- if (Peek () != '-')
- throw new ParserException (currentLine, currentColumn, "Expecting comment start tag");
- readToCurrTok ();
- currentTok += ReadLineUntil ("--");
- if (Peek (3) == "-->") {
- readToCurrTok (3);
- }else
- curState = States.BlockComment;
- saveAndResetCurrentTok (TokenType.BlockComment);
- break;
- default:
- throw new ParserException (currentLine, currentColumn, "error");
- }
- break;
- default:
- if (!(curState == States.Content || curState == States.XML || curState == States.init || curState == States.prolog))
- throw new ParserException (currentLine, currentColumn, "Unexpected char: '<'");
- if (Peek () == '/') {
- curState = States.EndTag;
- readToCurrTok ();
- saveAndResetCurrentTok (TokenType.ElementEnd);
- } else {
- curState = States.StartTag;
- saveAndResetCurrentTok (TokenType.ElementStart);
- }
-
- if (!nextCharIsValidCharStartName)
- throw new ParserException (currentLine, currentColumn, "Expected element name");
-
- readToCurrTok (true);
- while (nextCharIsValidCharName)
- readToCurrTok ();
-
- saveAndResetCurrentTok (TokenType.ElementName);
- break;
- }
- break;
- case '/':
- if (curState != States.StartTag)
- throw new ParserException (currentLine, currentColumn, "Unexpected char: '/'");
- readToCurrTok (true);
- if (Peek () != '>')
- throw new ParserException (currentLine, currentColumn, "Expecting '>'");
- readAndResetCurrentTok (TokenType.ElementEnd);
-
- curState = States.XML;
- break;
- case '>':
- readAndResetCurrentTok (TokenType.ElementClosing, true);
- switch (curState) {
- case States.EndTag:
- curState = States.XML;
- break;
- case States.StartTag:
- curState = States.Content;
- break;
- default:
- throw new ParserException (currentLine, currentColumn, "Unexpected char: '>'");
- }
- break;
- default:
- switch (curState) {
- case States.StartTag:
- if (!nextCharIsValidCharStartName)
- throw new ParserException (currentLine, currentColumn, "Expected attribute name");
- readToCurrTok (true);
- while (nextCharIsValidCharName)
- readToCurrTok ();
- saveAndResetCurrentTok (TokenType.AttributeName);
-
- SkipWhiteSpaces ();
-
- if (Peek () != '=')
- throw new ParserException (currentLine, currentColumn, "Expecting: '='");
- readAndResetCurrentTok (TokenType.Affectation, true);
-
- SkipWhiteSpaces ();
-
- char openAttVal = Peek ();
- if (openAttVal != '"' && openAttVal != '\'')
- throw new ParserException (currentLine, currentColumn, "Expecting attribute value enclosed either in '\"' or in \"'\"");
- readAndResetCurrentTok (TokenType.AttributeValueOpening, true);
-
- currentTok.Start = CurrentPosition;
- currentTok.Content = ReadLineUntil (new string (new char[]{ openAttVal }));
- saveAndResetCurrentTok (TokenType.AttributeValue);
-
- if (Peek () != openAttVal)
- throw new ParserException (currentLine, currentColumn, string.Format ("Expecting {0}", openAttVal));
- readAndResetCurrentTok (TokenType.AttributeValueClosing, true);
- break;
- default:
- throw new ParserException (currentLine, currentColumn, "unexpected char: " + Peek ());
- }
- break;
- }
- }
-
- if (cl.EndingState != (int)curState && currentLine < buffer.LineCount - 1)
- buffer [currentLine + 1].Tokens = null;
-
- cl.EndingState = (int)curState;
- }
-
- public override void SyntaxAnalysis ()
- {
- initSyntaxAnalysis ();
- Node currentNode = RootNode;
-
- for (int i = 0; i < buffer.LineCount; i++) {
- CodeLine cl = buffer[i];
- if (cl.Tokens == null)
- continue;
- cl.SyntacticNode = null;
-
- int tokPtr = 0;
- while (tokPtr < cl.Tokens.Count) {
- switch ((XMLParser.TokenType)cl.Tokens [tokPtr].Type) {
- case TokenType.ElementStart:
- tokPtr++;
- currentNode = addChildNode (currentNode, cl, tokPtr, "Element");
- break;
- case TokenType.ElementEnd:
- tokPtr++;
- if (tokPtr < cl.Tokens.Count) {
- if ((XMLParser.TokenType)cl.Tokens [tokPtr].Type == TokenType.ElementName &&
- cl.Tokens [tokPtr].Content != currentNode.Name)
- throw new ParserException (currentLine, currentColumn, "Closing tag mismatch");
- }
- closeNodeAndGoUp (ref currentNode, cl, "Element");
- break;
- case TokenType.ElementClosing:
- //currentNode = currentNode.Parent;
- break;
- default:
- break;
- }
- tokPtr++;
- }
- }
- }
- }
-}
-
+++ /dev/null
-//
-// SvgEditor.cs
-//
-// Author:
-// Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using System.ComponentModel;
-using Cairo;
-
-namespace Crow.Coding
-{
- public class SvgEditor : Editor
- {
- SvgPicture _pic = new SvgPicture();
-
- int zoom;
-
- [DefaultValue(100)]
- public int Zoom {
- get { return zoom; }
- set {
- if (zoom == value)
- return;
- zoom = value;
- NotifyValueChanged ("Zoom", zoom);
- updateMaxScrolls ();
- RegisterForGraphicUpdate ();
- }
- }
-
- void updateMaxScrolls() {
- MaxScrollX = Math.Max(0, _pic.Dimensions.Width * zoom / 100 - Slot.Width);
- MaxScrollY = Math.Max(0, _pic.Dimensions.Height * zoom / 100 - Slot.Height);
-
- if (Slot.Width + MaxScrollX > 0)
- NotifyValueChanged ("ChildWidthRatio", Slot.Width * Slot.Width / (Slot.Width + MaxScrollX));
- else
- NotifyValueChanged ("ChildWidthRatio", 0);
-
- if (Slot.Height + MaxScrollY > 0)
- NotifyValueChanged ("ChildHeightRatio", Slot.Height * Slot.Height / (Slot.Height + MaxScrollY));
- else
- NotifyValueChanged ("ChildHeightRatio", 0);
- }
- #region editor overrides
- protected override void updateEditorFromProjFile ()
- {
- Error = null;
- try {
- editorMutex.EnterWriteLock();
- _pic.LoadSvgFragment (projFile.Source);
- _pic.Scaled = true;
- _pic.KeepProportions = true;
- } catch (Exception ex) {
- Error = ex;
- }
- editorMutex.ExitWriteLock ();
- updateMaxScrolls ();
- RegisterForGraphicUpdate ();
- }
- protected override void updateProjFileFromEditor ()
- {
- throw new NotImplementedException ();
- }
- protected override bool EditorIsDirty {
- get { return false; }
- set {
- throw new NotImplementedException ();
- }
- }
- #endregion
-
- #region GraphicObject overrides
- protected override int measureRawSize (LayoutingType lt)
- {
- if (_pic == null)
- return 2 * Margin;
- //_pic = "#Crow.Images.Icons.IconAlerte.svg";
- //TODO:take scalling in account
- if (lt == LayoutingType.Width)
- return _pic.Dimensions.Width + 2 * Margin;
- else
- return _pic.Dimensions.Height + 2 * Margin;
- }
- protected override void onDraw (Context gr)
- {
- base.onDraw (gr);
-
- Rectangle r = ClientRectangle;
- Foreground.SetAsSource (gr, r);
- gr.Rectangle (r, 0.1);
- gr.Stroke ();
-
- r.Width = _pic.Dimensions.Width * zoom / 100;
- r.Height = _pic.Dimensions.Height * zoom / 100;
-
- gr.Save ();
-
- editorMutex.EnterReadLock ();
-
- gr.Translate (-ScrollX, -ScrollY);
- if (_pic != null)
- _pic.Paint (gr, r);
- editorMutex.ExitReadLock ();
-
- gr.Restore ();
- }
- public override void OnLayoutChanges (LayoutingType layoutType)
- {
- base.OnLayoutChanges (layoutType);
- if ((layoutType | LayoutingType.Sizing) > 0)
- updateMaxScrolls ();
- }
- #endregion
- }
-}
-
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<MenuItem MinimumSize="20,20" Height="Fit" Width="160" Caption="Context Menu" Data="{ContextCommands}" Orientation="Vertical"
+ IsOpened ="true" Visible="{/IsOpened}" SelectionBackground="Transparent">
+ <Template>
+ <Border Background="DimGray" Foreground="Black" CornerRadius="2">
+ <GenericStack Orientation="{./Orientation}" Name="ItemsContainer" Margin="2"/>
+ </Border>
+ </Template>
+ <ItemTemplate>
+ <MenuItem Command="{}" Width="150" PopWidth="120" SelectionBackground="Transparent" IsEnabled="{CanExecute}">
+ <Template>
+ <Popper Font="{./Font}" Caption="{./Caption}" Background="{./Background}" PopDirection="{./PopDirection}"
+ Foreground = "{./Foreground}" CanPop="{./HasChildren}" MouseDown="./onMI_Click"
+ IsPopped="{²./IsOpened}" PopWidth="{./PopWidth}" PopHeight="{./PopHeight}">
+ <Template>
+ <Border Name="border1"
+ CornerRadius="0"
+ MouseEnter="{Foreground=vgradient|0:White|0.2:Gray|0.9:Gray|1:Black}"
+ MouseLeave="{Foreground=Transparent}"
+ MouseDown="{Foreground=vgradient|0:Black|0.05:Gray|0.85:Gray|1:White}"
+ MouseUp="{Foreground=vgradient|0:White|0.2:Gray|0.9:Gray|1:Black}"
+ MinimumSize = "60,0"
+ Foreground="Transparent"
+ Background="{./Background}">
+ <HorizontalStack Spacing="5">
+ <Image Height="14" Width="14" Picture="{Icon}" />
+ <Label Text="{./Caption}"
+ Foreground="{./Foreground}"
+ Margin="1" HorizontalAlignment="Left"
+ Font="{./Font}" />
+ </HorizontalStack>
+ </Border>
+ </Template>
+ <Border Foreground="DimGray" Width="{../PopWidth}" Height="{../PopHeight}" Background="Onyx">
+ <VerticalStack Name="ItemsContainer"/>
+ </Border>
+ </Popper>
+ </Template>
+ </MenuItem>
+ </ItemTemplate>
+</MenuItem>
+
<MenuItem Caption="File" Width="Fit" PopWidth="120" DataSource="{CurrentSolution}">
<MenuItem Command="{CMDNew}" />
<MenuItem Command="{CMDOpen}" />
+ <MenuItem Command="{cmdCloseSolution}" />
<MenuItem DataSource="{SelectedItem}" Command="{cmdSave}" />
<MenuItem DataSource="{SelectedItem}" Command="{cmdSaveAs}" />
<MenuItem Command="{CMDQuit}" />
<?xml version="1.0"?>
<DockWindow DataSource="{CurrentSolution}" Name="winToolbox" Caption="Toolbox" Width="10%" Height="80%">
- <ListBox Margin="10" Data="{ToolboxItems}" SelectionBackground="SkyBlue">
+ <ListBox Margin="3" Data="{ToolboxItems}" SelectionBackground="SkyBlue">
<Template>
- <Wrapper Name="ItemsContainer" Orientation="Vertical" Margin="10" Spacing="3"/>
+ <Wrapper Name="ItemsContainer" Orientation="Vertical" Spacing="0"/>
</Template>
<ItemTemplate>
<Container Fit="true" Focusable="true" Tooltip="{DisplayName}" Margin="2" AllowDrag="true"
Foreground="Transparent" BorderWidth="1"
MouseDown="{Foreground=vgradient|0:Black|0.05:Gray|0.85:Gray|1:White}"
MouseUp="{Foreground=vgradient|0:White|0.2:Gray|0.9:Gray|1:Black}">
- <Image Path="{IconPath}" Margin="2" Width="20" Height="20" />
+ <Image Path="{IconPath}" Margin="3" Width="20" Height="20" />
</Border>
</Container>
</ItemTemplate>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-<TabView SelectedTab="{²./SelectedIndex}" Name="ItemsContainer" Orientation="Horizontal" />
+++ /dev/null
-<?xml version="1.0"?>
-<ItemTemplate>
- <TabItem Caption="{DisplayName}" QueryClose="OnQueryClose">
- <Label Text="Error" Background="Red"/>
- </TabItem>
-</ItemTemplate>
-<ItemTemplate DataType=".svg">
- <TabItem Caption="{DisplayName}" QueryClose="OnQueryClose">
- <VerticalStack>
- <HorizontalStack Height="50%" >
- <SvgEditor Margin="10" ProjectNode="{}" Focusable="true" Name="editor" MouseWheelSpeed="20" Foreground="Black"/>
- <ScrollBar Name="scrollbarY" Value="{²../editor.ScrollY}"
- LargeIncrement="10"
- CursorSize="{../editor.ChildHeightRatio}"
- Maximum="{../editor.MaxScrollY}" Orientation="Vertical"
- Width="14" />
- </HorizontalStack>
- <ScrollBar Style="HScrollBar" Name="scrollbarX" Value="{²../editor.ScrollX}"
- Maximum="{../editor.MaxScrollX}" Orientation="Horizontal"
- LargeIncrement="10"
- CursorSize="{../editor.ChildWidthRatio}"
- Height="14" />
- <HorizontalStack Height="Fit" Margin="3">
- <Label Text="Zoom:"/>
- <Label Text="{../../editor.Zoom}" Fit="true"/>
- <!--<Spinner Name="sldZoom" Value="{²../../editor.Zoom}" Maximum="800" Minimum="1" SmallIncrement="10" LargeIncrement="50" Width="40" />-->
- <Slider Value="{²../../editor.Zoom}" CursorSize="2" Height="8" Maximum="800" Minimum="1" SmallIncrement="1" LargeIncrement="10" Width="100" />
- </HorizontalStack>
-
- <Splitter/>
- <IMLContainer Path="#Crow.Coding.ui.SourceEditor.crow"/>
- <Label DataSource="{../editor.Error}" Text="{Message}"
- Visible="{../editor.HasError}"
- Height="Fit" Width="Stretched" Background="DarkRed" Foreground="White"
- TextAlignment="TopLeft" Multiline="true"/>
- </VerticalStack>
- </TabItem>
-</ItemTemplate>
-<ItemTemplate Path="#Crow.Coding.ui.SrcEdit.itemp" DataType=".cs"/>
-<ItemTemplate Path="#Crow.Coding.ui.SrcEdit.itemp" DataType=".style"/>
-<ItemTemplate Path="#Crow.Coding.ui.IMLEdit.itemp" DataType=".crow"/>
-<ItemTemplate Path="#Crow.Coding.ui.IMLEdit.itemp" DataType=".template"/>
<?xml version="1.0"?>
-<Expandable Caption="{Name}" >
+<Expandable Caption="{Name}" IsExpanded="{²IsExpanded}">
<Template>
<VerticalStack>
- <HorizontalStack Spacing="1" Height="Fit" MouseDoubleClick="./onClickForExpand" Background="{./Background}">
- <Container Margin="1" Width="10" Height="10" Focusable="true" MouseClick="./onClickForExpand"
- MouseEnter="{Background=LightGray}"
- MouseLeave="{Background=Transparent}">
- <Image
+ <Border CornerRadius="2" Margin="0" Height="Fit" MouseDoubleClick="./onClickForExpand"
+ Foreground="Transparent"
+ MouseEnter="{Foreground=DimGray}"
+ MouseLeave="{Foreground=Transparent}">
+ <HorizontalStack Spacing="1">
+ <Image Margin="1" Width="9" Height="9" Focusable="true" MouseDown="./onClickForExpand"
Path="{./Image}"
Visible="{./IsExpandable}"
- SvgSub="{./IsExpanded}"/>
- </Container>
- <Image Margin="2" Width="14" Height="14"
- Path="#Crow.Icons.folder.svg"/>
- <Label Text="{./Caption}"
- MouseEnter="{Background=hgradient|0:BlueCrayola|1:Transparent}"
+ SvgSub="{./IsExpanded}"
+ MouseEnter="{Background=LightGray}"
MouseLeave="{Background=Transparent}"/>
- </HorizontalStack>
+ <Border Width="16" Height="16" Foreground="Black" Background="White">
+ <Image Margin="2" Path="{GetIcon}" />
+ </Border>
+ <Label Text="{./Caption}"/>
+ </HorizontalStack>
+ </Border>
<Container Name="Content" Visible="false"/>
</VerticalStack>
</Template>
<HorizontalStack Height="Fit">
- <GraphicObject Width="12" Height="10"/>
- <TreeView Name="List" Height="Fit"
- Template="#Crow.Templates.treeList.template" />
+ <GraphicObject Width="8" Height="10"/>
+ <VerticalStack Height="Fit" Name="ItemsContainer"/>
</HorizontalStack>
</Expandable>
<?xml version="1.0"?>
-<Window Caption="Graphic Tree" Width="20%" Height="70%" AlwaysOnTop="true">
- <VerticalStack>
+<DockWindow Name="winGTExplorer" Caption="Edit View" Width="40%" Height="80%">
+ <VerticalStack Name="vstack" DataSource="{CurrentSolution}">
<Button Caption="Expand All" MouseClick="../treeView.onExpandAll_MouseClick"/>
- <TreeView IsRoot="true" Name="treeView" Data="{GraphicTree}"
- SelectedItemChanged="GTView_SelectedItemChanged">
-<!-- <Template>
- <HorizontalStack>
- <Scroller Name="scroller1" Margin="1" VerticalScrolling="true"
- Background="{./Background}"
- ScrollY="{../scrollbar1.Value}">
- <VerticalStack
- Height="Fit" Name="ItemsContainer" Margin="0" VerticalAlignment="Top"/>
- </Scroller>
- <ScrollBar
- Name="scrollbar1"
- Value="{../scroller1.ScrollY}"
- Maximum="{../scroller1.MaximumScroll}"
- Width="12" Orientation="Vertical"/>
- </HorizontalStack>
- </Template>-->
+ <TreeView DataSource="{SelectedItem}" IsRoot="true" Name="treeView" Data="{GraphicTree}"
+ SelectedItemChanged="../../vstack.DataSource.GTView_SelectedItemChanged">
<ItemTemplate>
- <HorizontalStack Width="Stretched" Focusable="true">
- <Label Text="{Name}"
- MouseEnter="{Background=hgradient|0:BlueCrayola|1:Transparent}"
- MouseLeave="{Background=Transparent}"/>
- </HorizontalStack>
+ <Border Width="Stretched" Focusable="true" Foreground="Transparent">
+ <HorizontalStack Spacing="5">
+ <Border Width="16" Height="16" Foreground="Black" Background="White">
+ <Image Margin="2" Path="{GetIcon}" />
+ </Border>
+ <Label Text="{Name}" Width="Stretched"/>
+ </HorizontalStack>
+ </Border>
</ItemTemplate>
<ItemTemplate DataType="Crow.Group" Data="GetChildren"
Path="#Crow.Coding.ui.GTreeExpITemp.crow"/>
Path="#Crow.Coding.ui.GTreeExpITemp.crow"/>
</TreeView>
</VerticalStack>
-</Window>
+</DockWindow>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-<TabItem Caption="{DisplayName}" QueryClose="OnQueryClose">
- <VerticalStack>
- <Label Width="Stretched" Margin="1" Text="{HoverWidget}"/>
- <ImlVisualEditor Height="60%" Margin="0" MinimumSize="10,10" Foreground="SkyBlue"
- AllowDrop="true"
- ProjectNode="{}" SelectedItem="{²SelectedItem}"
- Name="crowContainer" Background="Onyx"/>
- <Label DataSource="{../crowContainer.Error}" Text="{Message}"
- Visible="{../crowContainer.HasError}"
- Height="Fit" Width="Stretched" Background="DarkRed" Foreground="White"
- TextAlignment="TopLeft" Multiline="true"/>
- <Splitter/>
- <IMLContainer Path="#Crow.Coding.ui.SourceEditor.crow"/>
- </VerticalStack>
-</TabItem>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-<VerticalStack>
- <HorizontalStack Height="Stretched" >
- <SourceEditor Focusable="true" Name="editor" Font="monospace, 12" VerticalAlignment="Top" Margin="10"
- CurrentLine="{²CurrentLine}" CurrentColumn="{²CurrentColumn}"
- Foreground="Jet" Background="White" Width="Stretched" Height="Stretched"
- ProjectNode="{}" KeyDown="textView_KeyDown"/>
- <ScrollBar Name="scrollbarY" Value="{²../editor.ScrollY}"
- LargeIncrement="{../editor.VisibleLines}"
- CursorSize="{../editor.ChildHeightRatio}"
- Maximum="{../editor.MaxScrollY}" Orientation="Vertical"
- Width="14" />
- </HorizontalStack>
- <ScrollBar Style="HScrollBar" Name="scrollbarX" Value="{²../editor.ScrollX}"
- Maximum="{../editor.MaxScrollX}" Orientation="Horizontal"
- LargeIncrement="{../editor.VisibleColumns}"
- CursorSize="{../editor.ChildWidthRatio}"
- Height="14" />
- <HorizontalStack Height="Fit">
- <GraphicObject Height="5" Width="Stretched"/>
- <GraphicObject Background="Red" Width="5" Height="5" Visible="{IsDirty}"/>
- <Label Text="Line:" Foreground="Gray"/>
- <Label Text="{CurrentLine}"/>
- <GraphicObject Height="5" Width="10"/>
- <Label Text="column:" Foreground="Gray"/>
- <Label Text="{CurrentColumn}"/>
- <GraphicObject Height="5" Width="10"/>
- <Label Text="ScrollX:" Foreground="Gray"/>
- <Label Text="{../../editor.ScrollX}"/>
- </HorizontalStack>
-</VerticalStack>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-<TabItem Caption="{DisplayName}" QueryClose="OnQueryClose">
- <IMLContainer Path="#Crow.Coding.ui.SourceEditor.crow"/>
-</TabItem>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<TabView SelectedTab="{²./SelectedIndex}" Name="ItemsContainer" Orientation="Horizontal" />
--- /dev/null
+<?xml version="1.0"?>
+<ItemTemplate>
+ <TabItem Caption="{DisplayName}" QueryClose="OnQueryClose">
+ <Label Text="Error" Background="Red"/>
+ </TabItem>
+</ItemTemplate>
+<ItemTemplate Path="#Crow.Coding.ui.SvgEdit.itemp" DataType=".svg"/>
+<ItemTemplate Path="#Crow.Coding.ui.SrcEdit.itemp" DataType=".cs"/>
+<ItemTemplate Path="#Crow.Coding.ui.SrcEdit.itemp" DataType=".style"/>
+<ItemTemplate Path="#Crow.Coding.ui.IMLEdit.itemp" DataType=".crow"/>
+<ItemTemplate Path="#Crow.Coding.ui.IMLEdit.itemp" DataType=".template"/>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<TabItem Caption="{DisplayName}" QueryClose="OnQueryClose">
+ <VerticalStack>
+ <Label Width="Stretched" Margin="1" Text="{HoverWidget}"/>
+ <ImlVisualEditor Height="60%" Margin="0" MinimumSize="10,10" Foreground="SkyBlue"
+ AllowDrop="true" UpdateEnabled="{../../IsSelected}"
+ ProjectNode="{}" SelectedItem="{²SelectedItem}"
+ Name="crowContainer" Background="Onyx"/>
+ <Splitter/>
+ <IMLContainer Path="#Crow.Coding.ui.SourceEditor.crow"/>
+ <Label DataSource="{../crowContainer.Error}" Text="{Message}"
+ Visible="{../crowContainer.HasError}"
+ Height="Fit" Width="Stretched" Background="DarkRed" Foreground="White"
+ TextAlignment="TopLeft" Multiline="true"/>
+ </VerticalStack>
+</TabItem>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<VerticalStack>
+ <HorizontalStack >
+ <SourceEditor Focusable="true" Name="editor" Font="monospace, 12" VerticalAlignment="Top" Margin="10"
+ CurrentLine="{²CurrentLine}" CurrentColumn="{²CurrentColumn}"
+ Foreground="Jet" Background="White" Width="Stretched" Height="Stretched"
+ ProjectNode="{}" KeyDown="textView_KeyDown"/>
+ <ScrollBar Name="scrollbarY" Value="{²../editor.ScrollY}"
+ LargeIncrement="{../editor.VisibleLines}"
+ CursorSize="{../editor.ChildHeightRatio}"
+ Maximum="{../editor.MaxScrollY}" Orientation="Vertical"
+ Width="14" />
+ </HorizontalStack>
+ <ScrollBar Style="HScrollBar" Name="scrollbarX" Value="{²../editor.ScrollX}"
+ Maximum="{../editor.MaxScrollX}" Orientation="Horizontal"
+ LargeIncrement="{../editor.VisibleColumns}"
+ CursorSize="{../editor.ChildWidthRatio}"
+ Height="14" />
+ <HorizontalStack Height="Fit">
+ <GraphicObject Height="5" Width="Stretched"/>
+ <GraphicObject Background="Red" Width="5" Height="5" Visible="{IsDirty}"/>
+ <Label Text="Line:" Foreground="Gray"/>
+ <Label Text="{CurrentLine}"/>
+ <GraphicObject Height="5" Width="10"/>
+ <Label Text="column:" Foreground="Gray"/>
+ <Label Text="{CurrentColumn}"/>
+ <GraphicObject Height="5" Width="10"/>
+ <Label Text="ScrollX:" Foreground="Gray"/>
+ <Label Text="{../../editor.ScrollX}"/>
+ </HorizontalStack>
+</VerticalStack>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<TabItem Caption="{DisplayName}" QueryClose="OnQueryClose">
+ <IMLContainer Path="#Crow.Coding.ui.SourceEditor.crow"/>
+</TabItem>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<TabItem Caption="{DisplayName}" QueryClose="OnQueryClose">
+ <VerticalStack>
+ <VerticalStack Height="50%">
+ <HorizontalStack >
+ <SvgEditor Margin="10" ProjectNode="{}" Focusable="true" Name="editor" MouseWheelSpeed="20" Foreground="Black"/>
+ <ScrollBar Name="scrollbarY" Value="{²../editor.ScrollY}"
+ LargeIncrement="10"
+ CursorSize="{../editor.ChildHeightRatio}"
+ Maximum="{../editor.MaxScrollY}" Orientation="Vertical"
+ Width="14" />
+ </HorizontalStack>
+ <ScrollBar Style="HScrollBar" Name="scrollbarX" Value="{²../editor.ScrollX}"
+ Maximum="{../editor.MaxScrollX}" Orientation="Horizontal"
+ LargeIncrement="10"
+ CursorSize="{../editor.ChildWidthRatio}"
+ Height="14" />
+ <HorizontalStack Height="Fit" Margin="3">
+ <Label Text="Zoom:"/>
+ <Label Text="{../../editor.Zoom}" Fit="true"/>
+ <!--<Spinner Name="sldZoom" Value="{²../../editor.Zoom}" Maximum="800" Minimum="1" SmallIncrement="10" LargeIncrement="50" Width="40" />-->
+ <Slider Value="{²../../editor.Zoom}" CursorSize="2" Height="8" Maximum="800" Minimum="1" SmallIncrement="1" LargeIncrement="10" Width="100" />
+ </HorizontalStack>
+ </VerticalStack>
+ <Splitter/>
+ <IMLContainer Path="#Crow.Coding.ui.SourceEditor.crow"/>
+ <Label DataSource="{../editor.Error}" Text="{Message}"
+ Visible="{../editor.HasError}"
+ Height="Fit" Width="Stretched" Background="DarkRed" Foreground="White"
+ TextAlignment="TopLeft" Multiline="true"/>
+ </VerticalStack>
+</TabItem>
\ No newline at end of file
Stream s;
if (!string.IsNullOrEmpty (VertSourcePath)) {
- s = Crow.Interface.GetStreamFromPath (VertSourcePath);
+ s = Crow.Interface.StaticGetStreamFromPath (VertSourcePath);
if (s != null) {
using (StreamReader sr = new StreamReader (s)) {
vertSource = sr.ReadToEnd ();
}
if (!string.IsNullOrEmpty (FragSourcePath)) {
- s = Crow.Interface.GetStreamFromPath (FragSourcePath);
+ s = Crow.Interface.StaticGetStreamFromPath (FragSourcePath);
if (s != null) {
using (StreamReader sr = new StreamReader (s)) {
fragSource = sr.ReadToEnd ();
}
if (!string.IsNullOrEmpty (GeomSourcePath)) {
- s = Crow.Interface.GetStreamFromPath (GeomSourcePath);
+ s = Crow.Interface.StaticGetStreamFromPath (GeomSourcePath);
if (s != null) {
using (StreamReader sr = new StreamReader (s)) {
geomSource = sr.ReadToEnd ();
public Texture(string _mapPath, bool flipY = true)
{
- using (Stream s = Interface.GetStreamFromPath (_mapPath)) {
+ using (Stream s = Interface.StaticGetStreamFromPath (_mapPath)) {
try {
Map = _mapPath;
/// load the image for rendering from the path given as argument
/// </summary>
/// <param name="path">image path, may be embedded</param>
- public override void Load (string path)
+ public override void Load (Interface iface, string path)
{
Path = path;
if (sharedResources.ContainsKey (path)) {
Dimensions = sp.Dims;
return;
}
- using (Stream stream = Interface.GetStreamFromPath (path)) {
- using (MemoryStream ms = new MemoryStream ()) {
- stream.CopyTo (ms);
- loadBitmap (new System.Drawing.Bitmap (ms));
- }
+ using (Stream stream = iface.GetStreamFromPath (path)) {
+ loadBitmap (new System.Drawing.Bitmap (stream));
}
sharedResources [path] = new sharedPicture (image, Dimensions);
}
#region Reflexion helpers
static MemberInfo getMemberInfoWithReflexion(object instance, string member){
- return instance.GetType ().GetMember (member)?.FirstOrDefault();
+ Type t = instance.GetType();
+ MemberInfo mi = t.GetMember (member)?.FirstOrDefault();
+ if (mi == null)
+ mi = CompilerServices.SearchExtMethod (t, member);
+ return mi;
}
static MethodInfo getMethodInfoWithReflexion(object instance, string method){
return instance.GetType ().GetMethod (method, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
PropertyInfo pi = mi as PropertyInfo;
tmp = pi.GetValue (instance);
dstType = pi.PropertyType;
- }
- if (mi.MemberType == MemberTypes.Field) {
+ }else if (mi.MemberType == MemberTypes.Field) {
FieldInfo fi = mi as FieldInfo;
tmp = fi.GetValue (instance);
dstType = fi.FieldType;
+ }else if (mi.MemberType == MemberTypes.Method) {
+ MethodInfo gi = mi as MethodInfo;
+ if (gi.IsStatic)
+ tmp = gi.Invoke(null, new object[] {instance});
+ else
+ tmp = gi.Invoke(instance, null);
+ dstType = gi.ReturnType;
}
+
+
if (tmp != null)
return tmp;
if (dstType == typeof(string) || dstType == CompilerServices.TObject)//TODO:object should be allowed to return null and not ""
/// <summary>
/// create delegate helper
/// </summary>
- static Delegate createDel(Type eventType, object instance, string method){
+ static Delegate createDel(object instance, Type eventType, string method){
Type t = instance.GetType ();
MethodInfo mi = t.GetMethod (method, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (mi == null) {
handler(sender, e);
}
}
-
+ public static byte[] GetBytes(this string str)
+ {
+ byte[] bytes = new byte[str.Length * sizeof(char)];
+ System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
+ return bytes;
+ }
public static bool IsWhiteSpaceOrNewLine (this char c)
{
return c == '\t' || c == '\r' || c == '\n' || char.IsWhiteSpace (c);
IFace.currentLQI.NewSlot = Slot;
Debug.WriteLine ("\t\t{0} => {1}",LastSlots,Slot);
#endif
- #if DESIGN_MODE
- if (IFace.GetType().Name == "DesignInterface"){
- Debug.WriteLine ("\t\t{2}: {0} => {1}",LastSlots,Slot,this.name);
- }
- #endif
+// #if DESIGN_MODE
+// if (IFace.GetType().Name == "DesignInterface"){
+// Debug.WriteLine ("\t\t{2}: {0} => {1}",LastSlots,Slot,this.name);
+// }
+// #endif
switch (layoutType) {
case LayoutingType.Width:
this.RegisterForLayouting (LayoutingType.Sizing);
ChildrenCleared.Raise (this, new EventArgs ());
}
+ public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e)
+ {
+ base.OnDataSourceChanged (this, e);
+
+ childrenRWLock.EnterReadLock ();
+ foreach (GraphicObject g in Children) {
+ if (g.localDataSourceIsNull & g.localLogicalParentIsNull)
+ g.OnDataSourceChanged (g, e);
+ }
+ childrenRWLock.ExitReadLock ();
+ }
public void putWidgetOnTop(GraphicObject w)
{
}
#region GraphicObject overrides
- public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e)
- {
- base.OnDataSourceChanged (this, e);
- childrenRWLock.EnterReadLock ();
-
- foreach (GraphicObject g in children)
- if (g.localDataSourceIsNull & g.localLogicalParentIsNull)
- g.OnDataSourceChanged (g, e);
-
- childrenRWLock.ExitReadLock ();
- }
public override GraphicObject FindByName (string nameToFind)
{
if (Name == nameToFind)
{
Picture pic;
if (path.EndsWith (".svg", true, System.Globalization.CultureInfo.InvariantCulture))
- pic = new SvgPicture ();
+ pic = new SvgPicture (path);
else
- pic = new BmpPicture ();
+ pic = new BmpPicture (path);
- pic.Load (path);
+ pic.Load (IFace, path);
pic.Scaled = scaled;
pic.KeepProportions = keepProps;
}
}
- [XmlAttributeAttribute][DefaultValue(0)]
+ [DefaultValue(0)]
public int TabOffset {
get { return tabOffset; }
set {
public Measure TabWidth {
get { return tview == null ? Measure.Fit : tview.TabWidth; }
}
- [XmlAttributeAttribute][DefaultValue(false)]
+ [DefaultValue(false)]
public virtual bool IsSelected {
get { return isSelected; }
set {
/// <param name="bd">Bd.</param>
/// <param name="evt">passed as arg to prevent refetching it for the 3rd time</param>
public void emitHandlerMethodAddition(EventBinding bd){
+
//fetch source instance with address for handler addition (as 1st arg of handler.add)
il.Emit (OpCodes.Ldloc_0);//push root
CompilerServices.emitGetInstance (il, bd.SourceNA);
+ il.Emit (OpCodes.Ldloc_0);
+ CompilerServices.emitGetInstance (il, bd.TargetNA);
+
+ string[] membs = bd.TargetMember.Split ('.');
+ for (int i = 0; i < membs.Length - 1; i++) {
+ il.Emit (OpCodes.Dup);
+ il.Emit (OpCodes.Ldstr, membs[i]);
+ il.Emit (OpCodes.Call, CompilerServices.miGetMembIinfoWithRefx);
+ il.Emit (OpCodes.Call, CompilerServices.miGetValWithRefx);
+ }
+
//load handlerType of sourceEvent to create handler delegate (1st arg)
il.Emit (OpCodes.Ldtoken, bd.SourceEvent.EventHandlerType);
il.Emit (OpCodes.Call, CompilerServices.miGetTypeFromHandle);
- //load target the where the method is defined (2nd arg)
- il.Emit (OpCodes.Ldloc_0);
- CompilerServices.emitGetInstance (il, bd.TargetNA);
//load methodInfo (3rd arg)
- il.Emit (OpCodes.Ldstr, bd.TargetMember);
-
+ il.Emit (OpCodes.Ldstr, membs[membs.Length-1]);
il.Emit (OpCodes.Callvirt, CompilerServices.miCreateDel);
-
il.Emit (OpCodes.Callvirt, bd.SourceEvent.AddMethod);//call add event
}
-
+// public void emitHandlerMethodAddition(EventBinding bd){
+// //fetch source instance with address for handler addition (as 1st arg of handler.add)
+// il.Emit (OpCodes.Ldloc_0);//push root
+// CompilerServices.emitGetInstance (il, bd.SourceNA);
+//
+// //load handlerType of sourceEvent to create handler delegate (1st arg)
+// il.Emit (OpCodes.Ldtoken, bd.SourceEvent.EventHandlerType);
+// il.Emit (OpCodes.Call, CompilerServices.miGetTypeFromHandle);
+// //load target the where the method is defined (2nd arg)
+// il.Emit (OpCodes.Ldloc_0);
+// CompilerServices.emitGetInstance (il, bd.TargetNA);
+// //load methodInfo (3rd arg)
+// il.Emit (OpCodes.Ldstr, bd.TargetMember);
+//
+// il.Emit (OpCodes.Callvirt, CompilerServices.miCreateDel);
+//
+// il.Emit (OpCodes.Callvirt, bd.SourceEvent.AddMethod);//call add event
+// }
+//
}
}
\ No newline at end of file
/// <summary>
/// Initializes a new instance of the Instantiator class.
/// </summary>
- public Instantiator (Interface _iface, string path) : this (_iface, Interface.GetStreamFromPath(path), path) {
+ public Instantiator (Interface _iface, string path) : this (_iface, _iface.GetStreamFromPath(path), path) {
}
/// <summary>
if (iface.Instantiators.ContainsKey (itemTemplatePath)) {
itemTemplateIds.Add (new string [] { "default", itemTemplatePath, "" });
} else {
- using (Stream stream = Interface.GetStreamFromPath (itemTemplatePath)) {
+ using (Stream stream = iface.GetStreamFromPath (itemTemplatePath)) {
//itemtemplate files may have multiple root nodes
XmlReaderSettings itrSettings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment };
using (XmlReader itr = XmlReader.Create (stream, itrSettings)) {
}
}
- loadCursors ();
-
FontRenderingOptions = new FontOptions ();
FontRenderingOptions.Antialias = Antialias.Subpixel;
FontRenderingOptions.HintMetrics = HintMetrics.On;
public void Init () {
CurrentInterface = this;
+ loadCursors ();
loadStyling ();
findAvailableTemplates ();
initTooltip ();
}
}
- static void loadCursors(){
+ void loadCursors(){
//Load cursors
- XCursor.Cross = XCursorFile.Load("#Crow.Images.Icons.Cursors.cross").Cursors[0];
- XCursor.Default = XCursorFile.Load("#Crow.Images.Icons.Cursors.arrow").Cursors[0];
- XCursor.NW = XCursorFile.Load("#Crow.Images.Icons.Cursors.top_left_corner").Cursors[0];
- XCursor.NE = XCursorFile.Load("#Crow.Images.Icons.Cursors.top_right_corner").Cursors[0];
- XCursor.SW = XCursorFile.Load("#Crow.Images.Icons.Cursors.bottom_left_corner").Cursors[0];
- XCursor.SE = XCursorFile.Load("#Crow.Images.Icons.Cursors.bottom_right_corner").Cursors[0];
- XCursor.H = XCursorFile.Load("#Crow.Images.Icons.Cursors.sb_h_double_arrow").Cursors[0];
- XCursor.V = XCursorFile.Load("#Crow.Images.Icons.Cursors.sb_v_double_arrow").Cursors[0];
- XCursor.Text = XCursorFile.Load("#Crow.Images.Icons.Cursors.ibeam").Cursors[0];
+ XCursor.Cross = XCursorFile.Load(this, "#Crow.Images.Icons.Cursors.cross").Cursors[0];
+ XCursor.Default = XCursorFile.Load(this, "#Crow.Images.Icons.Cursors.arrow").Cursors[0];
+ XCursor.NW = XCursorFile.Load(this, "#Crow.Images.Icons.Cursors.top_left_corner").Cursors[0];
+ XCursor.NE = XCursorFile.Load(this, "#Crow.Images.Icons.Cursors.top_right_corner").Cursors[0];
+ XCursor.SW = XCursorFile.Load(this, "#Crow.Images.Icons.Cursors.bottom_left_corner").Cursors[0];
+ XCursor.SE = XCursorFile.Load(this, "#Crow.Images.Icons.Cursors.bottom_right_corner").Cursors[0];
+ XCursor.H = XCursorFile.Load(this, "#Crow.Images.Icons.Cursors.sb_h_double_arrow").Cursors[0];
+ XCursor.V = XCursorFile.Load(this, "#Crow.Images.Icons.Cursors.sb_v_double_arrow").Cursors[0];
+ XCursor.Text = XCursorFile.Load(this, "#Crow.Images.Icons.Cursors.ibeam").Cursors[0];
}
#endregion
/// <returns>A file or resource stream</returns>
/// <param name="path">This could be a normal file path, or an embedded ressource ID
/// Resource ID's must be prefixed with '#' character</param>
- public static Stream GetStreamFromPath (string path)
+ public virtual Stream GetStreamFromPath (string path)
+ {
+ Stream stream = null;
+
+ if (path.StartsWith ("#")) {
+ string resId = path.Substring (1);
+ //try/catch added to prevent nunit error
+ try {
+ stream = System.Reflection.Assembly.GetEntryAssembly ().GetManifestResourceStream (resId);
+ } catch{}
+ if (stream == null)//try to find ressource in Crow assembly
+ stream = System.Reflection.Assembly.GetExecutingAssembly ().GetManifestResourceStream (resId);
+ if (stream == null)
+ throw new Exception ("Resource not found: " + path);
+ } else {
+ if (!File.Exists (path))
+ throw new FileNotFoundException ("File not found: ", path);
+ stream = new FileStream (path, FileMode.Open, FileAccess.Read);
+ }
+ return stream;
+ }
+ public static Stream StaticGetStreamFromPath (string path)
{
Stream stream = null;
/// <param name="path">image path, may be embedded</param>
public Picture (string path)
{
- Load (path);
+ Path = path;
}
#endregion
/// load the image for rendering from the stream given as argument
/// </summary>
/// <param name="stream">picture stream</param>
- public abstract void Load(string path);
+ public abstract void Load(Interface iface, string path);
#endregion
/// <summary>
Picture _pic = null;
if (path.EndsWith (".svg", true, System.Globalization.CultureInfo.InvariantCulture))
- _pic = new SvgPicture ();
+ _pic = new SvgPicture (path);
else
- _pic = new BmpPicture ();
-
- _pic.Load (path);
+ _pic = new BmpPicture (path);
return _pic;
}
Picture _pic = null;
if (path.EndsWith (".svg", true, System.Globalization.CultureInfo.InvariantCulture))
- _pic = new SvgPicture ();
+ _pic = new SvgPicture (path);
else
- _pic = new BmpPicture ();
-
- _pic.Load (path);
+ _pic = new BmpPicture (path);
return _pic;
}
{}
#endregion
- public override void Load (string path)
+ public override void Load (Interface iface, string path)
{
Path = path;
if (sharedResources.ContainsKey (path)) {
Dimensions = sp.Dims;
return;
}
- using (Stream stream = Interface.GetStreamFromPath (path)) {
+ using (Stream stream = iface.GetStreamFromPath (path)) {
using (MemoryStream ms = new MemoryStream ()) {
stream.CopyTo (ms);
return tmp;
}
- public static XCursorFile Load(string path)
+ public static XCursorFile Load(Interface iface, string path)
{
- return loadFromStream (Interface.GetStreamFromPath (path));
+ return loadFromStream (iface.GetStreamFromPath (path));
}
static XCursor imageLoad(BinaryReader sr)