<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
- <OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
- <OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
public void Init ()
{
iface = new Interface ();
+ iface.Init ();
iface.ProcessResize (bounds);
}
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CrowIDE", "CrowIDE\CrowIDE.csproj", "{B6D911CD-1D09-42FC-B300-9187190F2AE1}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Crow.Coding", "..\gts\CrowEdit\Crow.Coding\Crow.Coding.csproj", "{78842EE4-8A2F-4C75-AEC6-C95F15AD3994}"
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
{C2980F9B-4798-4C05-99E2-E174810F7C7B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2980F9B-4798-4C05-99E2-E174810F7C7B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C2980F9B-4798-4C05-99E2-E174810F7C7B}.Release|Any CPU.Build.0 = Release|Any CPU
- {78842EE4-8A2F-4C75-AEC6-C95F15AD3994}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {78842EE4-8A2F-4C75-AEC6-C95F15AD3994}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {78842EE4-8A2F-4C75-AEC6-C95F15AD3994}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {78842EE4-8A2F-4C75-AEC6-C95F15AD3994}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
Policies = $0
$0.StandardHeader = $1
$1.Text = @\n${FileName}\n \nAuthor:\n ${AuthorName} <${AuthorEmail}>\n\nCopyright (c) 2013-2017 Jean-Philippe Bruyère\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.
+ $1.IncludeInNewFiles = True
$0.DotNetNamingPolicy = $2
+ $2.DirectoryNamespaceAssociation = None
+ $2.ResourceNamePolicy = FileFormatDefault
$0.TextStylePolicy = $3
+ $3.FileWidth = 120
+ $3.TabsToSpaces = False
$3.EolMarker = Unix
+ $3.inheritsSet = VisualStudio
+ $3.inheritsScope = text/plain
$3.scope = text/x-csharp
$0.CSharpFormattingPolicy = $4
$4.AfterDelegateDeclarationParameterComma = True
+ $4.inheritsSet = Mono
+ $4.inheritsScope = text/x-csharp
$4.scope = text/x-csharp
- $4.IndentSwitchSection = False
- $4.NewLinesForBracesInProperties = False
- $4.NewLinesForBracesInAccessors = False
- $4.NewLinesForBracesInAnonymousMethods = False
- $4.NewLinesForBracesInControlBlocks = False
- $4.NewLinesForBracesInAnonymousTypes = False
- $4.NewLinesForBracesInObjectCollectionArrayInitializers = False
- $4.NewLinesForBracesInLambdaExpressionBody = False
- $4.NewLineForElse = False
- $4.NewLineForCatch = False
- $4.NewLineForFinally = False
- $4.NewLineForMembersInObjectInit = False
- $4.NewLineForMembersInAnonymousTypes = False
- $4.NewLineForClausesInQuery = False
- $4.SpacingAfterMethodDeclarationName = True
- $4.SpaceAfterMethodCallName = True
- $4.SpaceBeforeOpenSquareBracket = True
$0.VersionControlPolicy = $5
$5.CommitMessageStyle = $6
$6.Indent = @\t
$6.LastFilePostfix = "@:\n "
$6.LineAlign = 0
$6.Wrap = False
+ $5.inheritsSet = Mono
description = @C.R.O.W. c# Rapid Open Widgets\n\nCrow is a pure c# widget toolkit with XML definition of interface, bindings, styling...\n
version = 0.5
EndGlobalSection
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{B6D911CD-1D09-42FC-B300-9187190F2AE1}</ProjectGuid>
<OutputType>Exe</OutputType>
- <RootNamespace>CrowIDE</RootNamespace>
+ <RootNamespace>Crow.Coding</RootNamespace>
<AssemblyName>CrowIDE</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<OutputPath>$(SolutionDir)build/$(Configuration)</OutputPath>
</CustomCommands>
</CustomCommands>
<ReleaseVersion>0.5</ReleaseVersion>
- <StartupObject>CrowIDE.CrowIDE</StartupObject>
+ <StartupObject>Crow.Coding.CrowIDE</StartupObject>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
- <IntermediateOutputPath>$(SolutionDir)build\obj\$(Configuration)</IntermediateOutputPath>
- <OutputPath>$(SolutionDir)build\$(Configuration)</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>0</WarningLevel>
<ConsolePause>false</ConsolePause>
- <IntermediateOutputPath>$(SolutionDir)build\obj\$(Configuration)</IntermediateOutputPath>
- <OutputPath>$(SolutionDir)build\$(Configuration)</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(RunConfiguration)' == 'Default' ">
<StartAction>Program</StartAction>
<Project>{C2980F9B-4798-4C05-99E2-E174810F7C7B}</Project>
<Name>Crow</Name>
</ProjectReference>
- <ProjectReference Include="..\..\gts\CrowEdit\Crow.Coding\Crow.Coding.csproj">
- <Project>{78842EE4-8A2F-4C75-AEC6-C95F15AD3994}</Project>
- <Name>Crow.Coding</Name>
- </ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="src\CrowIDE.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\Parser.cs" />
+ <Compile Include="src\SourceEditor\ParsingException.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" />
</ItemGroup>
<ItemGroup>
<Folder Include="ui\" />
<Folder Include="src\" />
<Folder Include="images\" />
+ <Folder Include="src\SourceEditor\" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="images\save.svg" />
<EmbeddedResource Include="ui\IDE.style" />
<EmbeddedResource Include="ui\MembersView.template">
- <LogicalName>CrowIDE.MembersView.template</LogicalName>
+ <LogicalName>Crow.Coding.MembersView.template</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="ui\LQIsExplorer.crow" />
<EmbeddedResource Include="ui\GTreeExplorer.crow" />
<EmbeddedResource Include="ui\ProjectTree.template" />
<EmbeddedResource Include="ui\MembersItem.template" />
<EmbeddedResource Include="ui\EditPane.template">
- <LogicalName>CrowIDE.EditPane.template</LogicalName>
+ <LogicalName>Crow.Coding.EditPane.template</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="ui\EditPaneItems.template" />
<EmbeddedResource Include="ui\CrowIDE.crow" />
using System.Xml;
using System.Linq;
using Crow.Coding;
+using System.Threading;
-namespace CrowIDE
+namespace Crow.Coding
{
class CrowIDE : CrowWindow
{
CMDCompile;
void initCommands () {
- CMDNew = new Command(new Action(() => newFile())) { Caption = "New", Icon = new SvgPicture("#CrowIDE.ui.icons.blank-file.svg"), CanExecute = false};
- CMDOpen = new Command(new Action(() => openFileDialog())) { Caption = "Open...", Icon = new SvgPicture("#CrowIDE.ui.icons.outbox.svg")};
- CMDSave = new Command(new Action(() => saveFileDialog())) { Caption = "Save", Icon = new SvgPicture("#CrowIDE.ui.icons.inbox.svg"), CanExecute = false};
- CMDSaveAs = new Command(new Action(() => saveFileDialog())) { Caption = "Save As...", Icon = new SvgPicture("#CrowIDE.ui.icons.inbox.svg"), CanExecute = false};
- CMDQuit = new Command(new Action(() => Quit (null, null))) { Caption = "Quit", Icon = new SvgPicture("#CrowIDE.ui.icons.sign-out.svg")};
- CMDUndo = new Command(new Action(() => undo())) { Caption = "Undo", Icon = new SvgPicture("#CrowIDE.ui.icons.reply.svg"), CanExecute = false};
- CMDRedo = new Command(new Action(() => redo())) { Caption = "Redo", Icon = new SvgPicture("#CrowIDE.ui.icons.share-arrow.svg"), CanExecute = false};
- CMDCut = new Command(new Action(() => Quit (null, null))) { Caption = "Cut", Icon = new SvgPicture("#CrowIDE.ui.icons.scissors.svg"), CanExecute = false};
- CMDCopy = new Command(new Action(() => Quit (null, null))) { Caption = "Copy", Icon = new SvgPicture("#CrowIDE.ui.icons.copy-file.svg"), CanExecute = false};
- CMDPaste = new Command(new Action(() => Quit (null, null))) { Caption = "Paste", Icon = new SvgPicture("#CrowIDE.ui.icons.paste-on-document.svg"), CanExecute = false};
- CMDHelp = new Command(new Action(() => System.Diagnostics.Debug.WriteLine("help"))) { Caption = "Help", Icon = new SvgPicture("#CrowIDE.ui.icons.question.svg")};
- CMDOptions = new Command(new Action(() => openOptionsDialog())) { Caption = "Editor Options", Icon = new SvgPicture("#CrowIDE.ui.icons.tools.svg")};
-
- CMDViewGTExp = new Command(new Action(() => loadWindow ("#CrowIDE.ui.GTreeExplorer.crow"))) { Caption = "Graphic Tree Explorer"};
- CMDViewProps = new Command(new Action(() => loadWindow ("#CrowIDE.ui.MemberView.crow"))) { Caption = "Properties View"};
+ CMDNew = new Command(new Action(() => newFile())) { Caption = "New", Icon = new SvgPicture("#Crow.Coding.ui.icons.blank-file.svg"), CanExecute = false};
+ CMDOpen = new Command(new Action(() => openFileDialog())) { Caption = "Open...", Icon = new SvgPicture("#Crow.Coding.ui.icons.outbox.svg")};
+ CMDSave = new Command(new Action(() => saveFileDialog())) { Caption = "Save", Icon = new SvgPicture("#Crow.Coding.ui.icons.inbox.svg"), CanExecute = false};
+ CMDSaveAs = new Command(new Action(() => saveFileDialog())) { Caption = "Save As...", Icon = new SvgPicture("#Crow.Coding.ui.icons.inbox.svg"), CanExecute = false};
+ CMDQuit = new Command(new Action(() => Quit (null, null))) { Caption = "Quit", Icon = new SvgPicture("#Crow.Coding.ui.icons.sign-out.svg")};
+ CMDUndo = new Command(new Action(() => undo())) { Caption = "Undo", Icon = new SvgPicture("#Crow.Coding.ui.icons.reply.svg"), CanExecute = false};
+ CMDRedo = new Command(new Action(() => redo())) { Caption = "Redo", Icon = new SvgPicture("#Crow.Coding.ui.icons.share-arrow.svg"), CanExecute = false};
+ CMDCut = new Command(new Action(() => Quit (null, null))) { Caption = "Cut", Icon = new SvgPicture("#Crow.Coding.ui.icons.scissors.svg"), CanExecute = false};
+ CMDCopy = new Command(new Action(() => Quit (null, null))) { Caption = "Copy", Icon = new SvgPicture("#Crow.Coding.ui.icons.copy-file.svg"), CanExecute = false};
+ CMDPaste = new Command(new Action(() => Quit (null, null))) { Caption = "Paste", Icon = new SvgPicture("#Crow.Coding.ui.icons.paste-on-document.svg"), CanExecute = false};
+ 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")};
+
+ CMDViewGTExp = new Command(new Action(() => loadWindow ("#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 ("#CrowIDE.ui.CSProjExplorer.crow"))) { Caption = "Project Explorer"};
+ CMDViewProj = new Command(new Action(() => loadWindow ("#Crow.Coding.ui.CSProjExplorer.crow"))) { Caption = "Project Explorer"};
CMDViewProjProps = new Command(new Action(loadProjProps) ){ Caption = "Project Properties"};
}
: base(1024, 800,"UIEditor")
{
}
- ImlVisualEditor imlVE;
Instantiator instFileDlg;
-
Solution currentSolution;
protected override void OnLoad (EventArgs e)
this.KeyDown += CrowIDE_KeyDown;
- //this.CrowInterface.LoadInterface ("#CrowIDE.ui.imlEditor.crow").DataSource = this;
+ //this.CrowInterface.LoadInterface ("#Crow.Coding.ui.imlEditor.crow").DataSource = this;
//GraphicObject go = this.CrowInterface.LoadInterface (@"ui/test.crow");
- GraphicObject go = AddWidget (@"#CrowIDE.ui.CrowIDE.crow");
- imlVE = go.FindByName ("crowContainer") as ImlVisualEditor;
+ GraphicObject go = AddWidget (@"#Crow.Coding.ui.CrowIDE.crow");
if (ReopenLastSolution && !string.IsNullOrEmpty(LastOpenSolution))
CurrentSolution = Solution.LoadSolution (LastOpenSolution);
}
void loadProjProps () {
- //loadWindow ("#CrowIDE.ui.ProjectProperties.crow", currentProject);
+ //loadWindow ("#Crow.Coding.ui.ProjectProperties.crow", currentProject);
}
void compileSolution () {
//ProjectItem pi = CurrentSolution.SelectedItem;
}
}// else if (e.Key == OpenTK.Input.Key.F6) {
-// loadWindow ("#CrowIDE.ui.LQIsExplorer.crow");
+// loadWindow ("#Crow.Coding.ui.LQIsExplorer.crow");
// } else if (e.Key == OpenTK.Input.Key.F7) {
-// loadWindow ("#CrowIDE.ui.CSProjExplorer.crow");
+// loadWindow ("#Crow.Coding.ui.CSProjExplorer.crow");
// }
}
void loadWindow(string path, object dataSource = null){
return;
g = CurrentInterface.AddWidget (path);
g.Name = path;
- if (dataSource == null)
- g.DataSource = imlVE;
- else
- g.DataSource = dataSource;
+ g.DataSource = dataSource;
} catch (Exception ex) {
System.Diagnostics.Debug.WriteLine (ex.ToString ());
}
using Crow;
using System.Globalization;
-namespace CrowIDE
+namespace Crow.Coding
{
public class DesignInterface : Interface, IValueChange
{
ValueChanged.Raise(this, new ValueChangeEventArgs(MemberName, _value));
}
#endregion
+
public DesignInterface ()
{
- CurrentInterface = this;
- CultureInfo.DefaultThreadCurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
}
- protected override void loadStyling ()
+ public ProjectFile ProjFile;
+
+ public override GraphicObject Load (string path)
{
- base.loadStyling ();
+ ProjectFile pi;
+ if (ProjFile.Project.solution.GetProjectFileFromPath (path, out pi))
+ return CreateITorFromIMLFragment (pi.Source).CreateInstance();
+ return null;
+ }
+ public override Crow.IML.Instantiator GetInstantiator (string path)
+ {
+ System.Diagnostics.Debugger.Break ();
+ return null;
}
+ public override ItemTemplate GetItemTemplate (string path)
+ {
+ ProjectFile pi;
+
+ if (ProjFile.Project.solution.GetProjectFileFromPath (path, out pi))
+ return new ItemTemplate (this, pi.AbsolutePath);
+ System.Diagnostics.Debugger.Break ();
+ return null;
+ }
public override bool ProcessMouseMove (int x, int y)
{
int deltaX = x - Mouse.X;
using Crow;
using System.Linq;
-namespace CrowIDE
+namespace Crow.Coding
{
public class EditPane : TemplatedGroup
{
public EditPane () : base()
{
}
- public override object SelectedItem {
- get { return base.SelectedItem; }
- set {
- base.SelectedItem = value;
- //Items.FirstOrDefault (i=>i.DataSource == value).
- }
- }
+
object selectedItemElement = null;
public object SelectedItemElement {
using System.Collections.Generic;
using Crow.IML;
-namespace CrowIDE
+namespace Crow.Coding
{
public class ImlVisualEditor : GraphicObject
{
#endregion
DesignInterface imlVE;
- Instantiator itor;
GraphicObject selectedItem;
- string imlSource;
- ProjectItem projectItem;
+ ImlProjectItem projectItem;
+ Exception imlError = null;
bool drawGrid;
int gridSpacing;
-
[XmlAttributeAttribute][DefaultValue(true)]
public bool DrawGrid {
get { return drawGrid; }
[XmlIgnore]public List<LQIList> LQIs {
get { return imlVE.LQIs; }
}
- [XmlIgnore]public string ImlSource {
- get { return imlSource; }
- set {
- if (imlSource == value)
- return;
- imlSource = value;
-
- NotifyValueChanged ("ImlSource", ImlSource);
-
- reloadFromSource ();
- }
- }
- [XmlAttributeAttribute][DefaultValue("")]
- public string ImlPath {
- get { return projectItem?.Path; }
- }
-
[XmlAttributeAttribute]
public ProjectNode ProjectNode {
if (projectItem == value)
return;
- if (!(value is ProjectItem))
- return;
- projectItem = value as ProjectItem;
+ if (projectItem != null)
+ projectItem.ValueChanged -= ProjectItem_ValueChanged;
+
+ projectItem = value as ImlProjectItem;
- NotifyValueChanged ("ImlPath", ImlPath);
+ if (projectItem != null)
+ projectItem.ValueChanged += ProjectItem_ValueChanged;
- reloadFromPath ();
+ NotifyValueChanged ("ProjectNode", projectItem);
+
+ reload ();
}
}
- public List<GraphicObject> GraphicTree {
- get { return imlVE.GraphicTree; }
+
+ void ProjectItem_ValueChanged (object sender, ValueChangeEventArgs e)
+ {
+ if (e.MemberName == "Source")
+ reload ();
}
- void reloadFromSource(){
- if (string.IsNullOrEmpty (imlSource)) {
- reload_iTor (null);
- return;
+ [XmlIgnore]public Exception IMLError {
+ get { return imlError; }
+ set {
+ if (imlError == value)
+ return;
+ imlError = value;
+ NotifyValueChanged ("IMLError", imlError);
}
+ }
- Instantiator iTmp;
+ void reload(){
+ if (projectItem == null)
+ return;
+
try {
- iTmp = Instantiator.CreateFromImlFragment (imlVE, imlSource);
+ imlVE.ProjFile = projectItem;
+ imlVE.Styling = projectItem.Project.solution.Styling;
+ imlVE.DefaultTemplates = projectItem.Project.solution.DefaultTemplates;
+ imlVE.Instantiators = new Dictionary<string, Instantiator>();
+ imlVE.ClearInterface();
+ imlVE.LoadIMLFragment(projectItem.Source);
+ IMLError = null;
} catch (Exception ex) {
- System.Diagnostics.Debug.WriteLine (ex.ToString());
- return;
- }
-
- reload_iTor (iTmp);
- }
- void reloadFromPath(){
- string path = Path.Combine (projectItem?.Project.RootDir,projectItem?.Path);
- if (!File.Exists (path)){
- System.Diagnostics.Debug.WriteLine ("Path not found: " + path);
- reload_iTor (null);
- return;
- }
- using (StreamReader sr = new StreamReader (path)) {
- ImlSource = sr.ReadToEnd ();
+ IMLError = ex;
}
- NotifyValueChanged ("GraphicTree", null);
- NotifyValueChanged ("GraphicTree", GraphicTree);
- SelectedItem = null;
}
- void reload_iTor(Instantiator new_iTot){
- itor = new_iTot;
- lock (imlVE.UpdateMutex) {
- try {
- imlVE.ClearInterface ();
- if (itor != null)
- imlVE.AddWidget(itor.CreateInstance());
- } catch (Exception ex) {
- System.Diagnostics.Debug.WriteLine (ex.ToString());
- }
- }
+ public List<GraphicObject> GraphicTree {
+ get { return imlVE.GraphicTree; }
}
void interfaceThread()
RegisterForRedraw ();
}
- Thread.Sleep (2);
+ Thread.Sleep (10);
}
}
gr.Rectangle (hr, 1.0);
}
- if (SelectedItem == null)
+ if (SelectedItem?.Parent == null)
return;
hr = SelectedItem.ScreenCoordinates(SelectedItem.getSlot ());
hr.Inflate (1);
using System.Collections.Generic;
using System.Linq;
-namespace CrowIDE
+namespace Crow.Coding
{
public class PropertyContainer : IValueChange
{
using Crow;
using System.Text.RegularExpressions;
-namespace CrowIDE
+namespace Crow.Coding
{
public class Project: IValueChange
{
}
return tmp;
}
- public string Compile () {
- GetStyling ();
-
+ public string Compile () {
if (ParentProject != null)
ParentProject.Compile ();
solution.UpdateErrorList ();
return parameters.OutputAssembly;
- }
+ }
+
+ public bool GetProjectFileFromPath (string path, out ProjectFile pi){
+ if (path.StartsWith ("#"))
+ pi = flattenNodes.OfType<ProjectFile> ().FirstOrDefault
+ (pp => pp.Type == ItemType.EmbeddedResource && pp.ResourceID == path.Substring (1));
+ else
+ pi = flattenNodes.OfType<ProjectFile> ().FirstOrDefault (pp => pp.Path == path);
+
+ if (pi != null)
+ return true;
+
+ foreach (ProjectReference pr in flattenNodes.OfType<ProjectReference>()) {
+ Project p = solution.Projects.FirstOrDefault (pp => pp.ProjectGuid == pr.ProjectGUID);
+ if (p == null)
+ throw new Exception ("referenced project not found");
+ if (p.GetProjectFileFromPath (path, out pi))
+ return true;
+ }
+ //TODO: search referenced assemblies
+ return false;
+ }
+
+ public void GetDefaultTemplates () {
+ IEnumerable<ProjectFile> tmpFiles =
+ flattenNodes.OfType<ProjectFile> ().Where (pp => pp.Extension == ".template" );
+
+ foreach (ProjectFile pi in tmpFiles.Where(
+ pp=>pp.Type == ItemType.None && pp.CopyToOutputDirectory != CopyToOutputState.Never)) {
+
+ string clsName = System.IO.Path.GetFileNameWithoutExtension(pi.Path);
+ if (solution.DefaultTemplates.ContainsKey (clsName))
+ continue;
+ solution.DefaultTemplates [clsName] = pi.AbsolutePath;
+ }
+ foreach (ProjectFile pi in tmpFiles.Where(pp=>pp.Type == ItemType.EmbeddedResource)) {
+ string resId = pi.ResourceID;
+ string clsName = resId.Substring (0, resId.Length - 9);
+ if (solution.DefaultTemplates.ContainsKey (clsName))
+ continue;
+ solution.DefaultTemplates [clsName] = pi.Path;
+ }
+
+ foreach (ProjectReference pr in flattenNodes.OfType<ProjectReference>()) {
+ Project p = solution.Projects.FirstOrDefault (pp => pp.ProjectGuid == pr.ProjectGUID);
+ if (p == null)
+ throw new Exception ("referenced project not found");
+ p.GetDefaultTemplates ();
+ }
+ }
+// void searchTemplatesIn(Assembly assembly){
+// if (assembly == null)
+// return;
+// foreach (string resId in assembly
+// .GetManifestResourceNames ()
+// .Where (r => r.EndsWith (".template", StringComparison.OrdinalIgnoreCase))) {
+// string clsName = resId.Substring (0, resId.Length - 9);
+// if (DefaultTemplates.ContainsKey (clsName))
+// continue;
+// DefaultTemplates[clsName] = "#" + resId;
+// }
+// }
-
public void GetStyling () {
- foreach (ProjectFile pi in flattenNodes.OfType<ProjectFile> ().Where (pp=>pp.Type == ItemType.EmbeddedResource)) {
- Console.WriteLine (pi.Extension);
- }
+ foreach (ProjectFile pi in flattenNodes.OfType<ProjectFile> ().Where (pp=>pp.Type == ItemType.EmbeddedResource && pp.Extension == ".style")) {
+ using (Stream s = new MemoryStream (System.Text.Encoding.UTF8.GetBytes(pi.Source))) {
+ new StyleReader (solution.Styling, s, pi.ResourceID);
+ }
+ }
+ foreach (ProjectReference pr in flattenNodes.OfType<ProjectReference>()) {
+ Project p = solution.Projects.FirstOrDefault (pp => pp.ProjectGuid == pr.ProjectGUID);
+ if (p == null)
+ throw new Exception ("referenced project not found");
+ p.GetStyling();
+ }
+
+ //TODO:get styling from referenced assemblies
}
}
}
using System.IO;
using Crow;
-namespace CrowIDE
+namespace Crow.Coding
{
public enum ItemType {
ReferenceGroup,
}
public class ProjectFile : ProjectItem {
bool isDirty = false;
+ bool isOpened = false;
+// bool isSelected = false;
+ DateTime accessTime;
+ string source;
object selectedItem;
+
public ProjectFile (ProjectItem pi) : base (pi.Project, pi.node){
}
+ public string ResourceID {
+ get {
+ return Type != ItemType.EmbeddedResource ? null :
+ node.SelectSingleNode ("LogicalName") == null ?
+ Project.Name + "." + Path.Replace ('/', '.') :
+ LogicalName;
+ }
+ }
public string LogicalName {
get {
return node.SelectSingleNode ("LogicalName")?.InnerText;
}
public string Source {
get {
- using (StreamReader sr = new StreamReader (AbsolutePath)) {
- return sr.ReadToEnd ();
- }
+ if (!isOpened) {
+ accessTime = System.IO.File.GetLastWriteTime (AbsolutePath);
+ using (StreamReader sr = new StreamReader (AbsolutePath)) {
+ source = sr.ReadToEnd ();
+ }
+ isOpened = true;
+ isDirty = false;
+ } else {
+ if (DateTime.Compare (
+ accessTime,
+ System.IO.File.GetLastWriteTime (AbsolutePath)) < 0)
+ Console.WriteLine ("File has been modified outside CrowIDE");
+ }
+ return source;
+ }
+ set {
+ if (source == value)
+ return;
+ source = value;
+ NotifyValueChanged ("Source", source);
}
}
+
+// public bool IsSelected {
+// get { return isSelected; }
+// set {
+// if (isSelected == value)
+// return;
+// isSelected = value;
+// NotifyValueChanged ("IsSelected", isSelected);
+// }
+// }
+
public object SelectedItem {
get { return selectedItem; }
set {
using System.Xml.Serialization;
using Crow;
-namespace CrowIDE{
+namespace Crow.Coding{
public class SolutionProject {
public string ProjectHostGuid;
public string ProjectName;
object selectedItemElement = null;
ObservableList<ProjectItem> openedItems = new ObservableList<ProjectItem>();
+ public Dictionary<string, Style> Styling;
+ public Dictionary<string, string> DefaultTemplates;
+
+ //TODO: check project dependencies if no startup proj
+
+ public void ReloadStyling () {
+ Styling = new Dictionary<string, Style> ();
+ if (StartupProject != null)
+ StartupProject.GetStyling ();
+ }
+
+ public void ReloadDefaultTemplates () {
+ DefaultTemplates = new Dictionary<string, string>();
+ if (StartupProject != null)
+ StartupProject.GetDefaultTemplates ();
+ }
+ public bool GetProjectFileFromPath (string path, out ProjectFile pi){
+ pi = null;
+ return StartupProject == null ? false :
+ StartupProject.GetProjectFileFromPath (path, out pi);
+ }
+
+
public ObservableList<ProjectItem> OpenedItems {
get { return openedItems; }
set {
value.NotifyValueChanged("IsStartupProject", true);
}
NotifyValueChanged ("StartupProject", StartupProject);
-
+ ReloadStyling ();
+ ReloadDefaultTemplates ();
}
}
));
s.UserConfig = new Configuration (s.path + ".user");
-
+ s.ReloadStyling ();
+ s.ReloadDefaultTemplates ();
return s;
} //LoadSolution
#endregion
// THE SOFTWARE.
using System;
-namespace CrowIDE
+namespace Crow.Coding
{
public class SolutionControler
{
--- /dev/null
+using System;
+using Crow;
+
+namespace Crow.Coding
+{
+ public class CSharpParser : Parser
+ {
+ public new enum TokenType {
+ Unknown = Parser.TokenType.Unknown,
+ WhiteSpace = Parser.TokenType.WhiteSpace,
+ LineComment = Parser.TokenType.LineComment,
+ BlockComment = Parser.TokenType.BlockComment,
+ OpenParenth,
+ CloseParenth,
+ OpenBlock,
+ CloseBlock,
+ StatementEnding,
+ UnaryOp,
+ BinaryOp,
+ Affectation,
+ StringLiteral,
+ CharacterLiteral,
+ DigitalLiteral,
+ Literal,
+ Identifier,
+ Indexer,
+ Type,
+ Preprocessor,
+ }
+
+ public CSharpParser (CodeBuffer _buffer) : base(_buffer)
+ {
+ }
+
+ public override void ParseCurrentLine ()
+ {
+ throw new NotImplementedException ();
+ }
+ public override void SyntaxAnalysis ()
+ {
+ throw new NotImplementedException ();
+ }
+ }
+}
+
--- /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;
+
+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 object EditMutex = new object();
+ //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
+
+ #region CTOR
+ public CodeBuffer () {
+
+ }
+ #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;
+ lock (EditMutex) {
+ lines [i] = value;
+ LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i));
+ }
+ }
+ }
+
+ public void RemoveAt(int i){
+ lock (EditMutex) {
+ lines.RemoveAt (i);
+ LineRemoveEvent.Raise (this, new CodeBufferEventArgs (i));
+ }
+ }
+ public void Insert(int i, string item){
+ lock (EditMutex) {
+ lines.Insert (i, item);
+ LineAdditionEvent.Raise (this, new CodeBufferEventArgs (i));
+ }
+ }
+ public void Add(CodeLine item){
+ lock (EditMutex) {
+ lines.Add (item);
+ LineAdditionEvent.Raise (this, new CodeBufferEventArgs (lines.Count - 1));
+ }
+ }
+ public void AddRange (string[] items){
+ int start = lines.Count;
+ lock (EditMutex) {
+ for (int i = 0; i < items.Length; i++)
+ lines.Add (items [i]);
+ LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length));
+ }
+ }
+ public void AddRange (CodeLine[] items){
+ int start = lines.Count;
+ lock (EditMutex) {
+ lines.AddRange (items);
+ LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length));
+ }
+ }
+ public void Clear () {
+ lock (EditMutex) {
+ longestLineCharCount = 0;
+ lines.Clear ();
+ BufferCleared.Raise (this, null);
+ }
+ }
+ public void UpdateLine(int i, string newContent){
+ lock (EditMutex) {
+ this [i].Content = newContent;
+ LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i));
+ }
+ }
+ public void AppenedLine(int i, string newContent){
+ lock (EditMutex) {
+ this [i].Content += newContent;
+ LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i));
+ }
+ }
+ public void ToogleFolding (int line) {
+ if (!this [line].IsFoldable)
+ return;
+ lock (EditMutex) {
+ this [line].IsFolded = !this [line].IsFolded;
+ FoldingEvent.Raise (this, new CodeBufferEventArgs (line));
+ }
+ }
+ public void Load(string rawSource) {
+ this.Clear();
+
+ if (string.IsNullOrEmpty (rawSource))
+ return;
+
+ AddRange (Regex.Split (rawSource, "\r\n|\r|\n|\\\\n"));
+
+ 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;
+ for (int i = 0; i < this.LineCount; i++) {
+ if (lines[i].PrintableLength > longestLineCharCount) {
+ longestLineCharCount = lines[i].PrintableLength;
+ longestLineIdx = i;
+ }
+ }
+ 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 = "";
+ for (int i = 0; i < lines.Count -1; i++)
+ tmp += lines [i].Content + this.lineBreak;
+ tmp += lines [lines.Count - 1].Content;
+ return tmp;
+ }
+ }
+
+ /// <summary>
+ /// unfolded and not in folds line count
+ /// </summary>
+ public int UnfoldedLines {
+ get {
+ int i = 0, vl = 0;
+ while (i < LineCount) {
+ if (this [i].IsFolded)
+ i = GetEndNodeIndex (i);
+ i++;
+ vl++;
+ }
+ //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);
+ }
+ /// <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);
+ }
+ /// <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; } }
+ /// <summary>
+ /// Current column in buffer coordinate, tabulation = 1 char
+ /// </summary>
+ public int CurrentColumn{
+ get { return _currentCol; }
+ set {
+ if (value == _currentCol)
+ return;
+ if (value < 0)
+ _currentCol = 0;
+ else if (value > lines [_currentLine].Length)
+ _currentCol = lines [_currentLine].Length;
+ else
+ _currentCol = value;
+
+ 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;
+ if (value >= lines.Count)
+ _currentLine = lines.Count-1;
+ else if (value < 0)
+ _currentLine = 0;
+ else
+ _currentLine = value;
+
+ if (_currentCol > lines [_currentLine].Length)
+ _currentCol = lines [_currentLine].Length;
+ Debug.WriteLine ("buff cur line: " + _currentLine);
+ 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()
+ {
+ lock (EditMutex) {
+ if (SelectionIsEmpty) {
+ if (CurrentColumn == 0) {
+ if (CurrentLine == 0)
+ return;
+ CurrentLine--;
+ CurrentColumn = this [CurrentLine].Length;
+ AppenedLine (CurrentLine, this [CurrentLine + 1].Content);
+ RemoveAt (CurrentLine + 1);
+ 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 ();
+ }
+ }
+ }
+ /// <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;
+
+namespace Crow.Coding
+{
+ public class CodeLine
+ {
+ public string Content;
+ public List<Token> Tokens;
+ public int EndingState = 0;
+ public Node SyntacticNode;
+ public ParsingException 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; } }
+ 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 void SetLineInError (ParsingException 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 override string ToString ()
+ {
+ return string.Format ("Name:{0}, Type:{1}\n\tparent:{2}", Name, Type, Parent);
+ }
+ }
+}
+
--- /dev/null
+using System;
+using System.IO;
+using Crow;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace Crow.Coding
+{
+ /// <summary>
+ /// base class for tokenizing sources
+ /// </summary>
+ public abstract class Parser
+ {
+ /// <summary>
+ /// Default tokens, this enum may be overriden in derived parser with the new keyword,
+ /// see XMLParser for example.
+ /// </summary>
+ public enum TokenType {
+ Unknown,
+ WhiteSpace,
+ NewLine,
+ LineComment,
+ BlockCommentStart,
+ BlockComment,
+ BlockCommentEnd,
+ Type,
+ Identifier,
+ Indexer,
+ OpenBlock,
+ CloseBlock,
+ StatementEnding,
+ UnaryOp,
+ BinaryOp,
+ Affectation,
+ StringLitteralOpening,
+ StringLitteralClosing,
+ StringLitteral,
+ NumericLitteral,
+ Preprocessor,
+ }
+
+ #region CTOR
+ public Parser (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
+
+ 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 ParsingException(parser, "closing tag not corresponding"));
+ // }
+ //
+ // }
+ // }
+ }
+ 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 ParsingException)
+ SetLineInError (ex as ParsingException);
+ }
+ }
+ 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 ParsingException)
+ SetLineInError (ex as ParsingException);
+ }
+
+ }
+
+ protected CodeBuffer buffer;
+
+ internal int currentLine = 0;
+ internal int currentColumn = 0;
+ protected Token currentTok;
+ protected bool eol = true;
+
+ public Node RootNode;
+
+ protected Point CurrentPosition {
+ get { return new Point (currentLine, currentColumn); }
+ set {
+ currentLine = value.Y;
+ currentColumn = value.X;
+ }
+ }
+
+ public abstract void ParseCurrentLine();
+ public abstract void SyntaxAnalysis ();
+
+ public virtual void SetLineInError(ParsingException 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);
+ }
+
+ #region low level parsing
+ /// <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 ();
+ }
+ /// <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 ParsingException (this, "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 ParsingException (this, "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;
+ }
+ /// <summary>
+ /// read until end of line is reached
+ /// </summary>
+ /// <returns>string read</returns>
+ protected virtual string ReadLine () {
+ string tmp = "";
+ while (!eol)
+ tmp += Read ();
+ return tmp;
+ }
+ /// <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 ParsingException (this, "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
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+
+namespace Crow.Coding
+{
+ public class ParsingException : Exception
+ {
+ public int Line;
+ public int Column;
+ public ParsingException(Parser parser, string txt)
+ : base(string.Format("Parser exception ({0},{1}): {2}", parser.currentLine, parser.currentColumn, txt))
+ {
+ Line = parser.currentLine;
+ Column = parser.currentColumn;
+ }
+ public ParsingException(Parser parser, string txt, Exception innerException)
+ : base(txt, innerException)
+ {
+ txt = string.Format("Parser exception ({0},{1}): {2}", parser.currentLine, parser.currentColumn, txt);
+ }
+ }
+}
+
--- /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 : ScrollingObject
+ {
+ #region CTOR
+ public SourceEditor (): base()
+ {
+ formatting.Add ((int)XMLParser.TokenType.AttributeName, new TextFormatting (Color.UnitedNationsBlue, 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.Affectation, 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.OrangeRed, Color.Transparent, false, true));
+ formatting.Add ((int)XMLParser.TokenType.XMLDecl, new TextFormatting (Color.GreenCrayola, Color.Transparent));
+ formatting.Add ((int)XMLParser.TokenType.BlockComment, new TextFormatting (Color.Gray, Color.Transparent, false, true));
+
+ parsing.Add (".crow", "Crow.Coding.XMLParser");
+
+ 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(""));
+
+ Thread updateSource = new Thread (updateSourceThreadFunc);
+ updateSource.IsBackground = true;
+ updateSource.Start ();
+ }
+ #endregion
+ string oldSource = "";
+ void updateSourceThreadFunc (){
+ while (true) {
+ if (projNode != null && buffer != null) {
+ string newSrc = buffer.FullText;
+ if (projNode.Source != newSrc)
+ projNode.Source = newSrc;
+ }
+ Thread.Sleep (100);
+ }
+ }
+ const int leftMarginGap = 3;//gap between items in margin and text
+ const int foldSize = 9;//folding rectangles size
+
+ #region private and protected fields
+ bool foldingEnabled = true;
+ ProjectFile projNode = null;
+ int leftMargin = 0; //margin used to display line numbers, folding errors,etc...
+ int visibleLines = 1;
+ int visibleColumns = 1;
+ CodeBuffer buffer;
+ Parser parser;
+ Color selBackground;
+ Color selForeground;
+// int _currentCol; //0 based cursor position in string
+// int _currentLine;
+
+
+ Dictionary<int, TextFormatting> formatting = new Dictionary<int, TextFormatting>();
+ Dictionary<string, string> parsing = new Dictionary<string, string>();
+
+ protected Rectangle rText;
+ protected FontExtents fe;
+ protected TextExtents te;
+ #endregion
+
+ void measureLeftMargin () {
+ leftMargin = 0;
+ if (PrintLineNumbers)
+ leftMargin += (int)Math.Ceiling((double)buffer.LineCount.ToString().Length * fe.MaxXAdvance) +6;
+ if (foldingEnabled)
+ leftMargin += foldSize;
+ if (leftMargin > 0)
+ leftMargin += leftMarginGap;
+ updateVisibleColumns ();
+ }
+ void findLongestLineAndUpdateMaxScrollX() {
+ buffer.FindLongestVisualLine ();
+ MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns);
+ 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.Height);
+ NotifyValueChanged ("VisibleLines", visibleLines);
+ updateMaxScrollY ();
+ updatePrintedLines ();
+ 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);
+ MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns);
+
+ System.Diagnostics.Debug.WriteLine ("update visible columns: {0} leftMargin:{1}",visibleColumns, leftMargin);
+ System.Diagnostics.Debug.WriteLine ("update MaxScrollX: " + MaxScrollX);
+ }
+ 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);
+ }
+ }
+
+ int firstPrintedLine = -1;
+ /// <summary>
+ /// list of lines visible in the Editor depending on scrolling and folding
+ /// </summary>
+ List<CodeLine> PrintedLines;
+
+ void updatePrintedLines () {
+ lock (buffer.EditMutex) {
+ 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++;
+ }
+ }
+ RegisterForGraphicUpdate ();
+ }
+ void toogleFolding (int line) {
+ if (parser == null || !foldingEnabled)
+ return;
+ buffer.ToogleFolding (line);
+ }
+
+ #region Buffer events handlers
+ void Buffer_BufferCleared (object sender, EventArgs e)
+ {
+ buffer.longestLineCharCount = 0;
+ buffer.longestLineIdx = 0;
+ measureLeftMargin ();
+ MaxScrollX = MaxScrollY = 0;
+ PrintedLines = null;
+ RegisterForGraphicUpdate ();
+ }
+ 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);
+ }
+ measureLeftMargin ();
+
+ if (parser != null)
+ parser.reparseSource ();
+
+ updatePrintedLines ();
+ updateMaxScrollY ();
+ RegisterForGraphicUpdate ();
+ }
+ 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 ();
+ }
+ 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 ();
+ }
+ void Buffer_PositionChanged (object sender, EventArgs e)
+ {
+ updateOnScreenCurLineFromBuffCurLine ();
+ }
+
+ void Buffer_SelectionChanged (object sender, EventArgs e)
+ {
+ RegisterForGraphicUpdate ();
+ }
+ void Buffer_FoldingEvent (object sender, CodeBufferEventArgs e)
+ {
+ updatePrintedLines ();
+ updateMaxScrollY ();
+ RegisterForGraphicUpdate ();
+ }
+ #endregion
+
+ Parser 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 (Parser)Activator.CreateInstance (parserType, buffer );
+ }
+
+ #region Public Crow Properties
+ [XmlAttributeAttribute]
+ 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 ();
+ }
+ }
+ [XmlAttributeAttribute]
+ public ProjectFile ProjectNode
+ {
+ get {
+ return projNode;
+ }
+ set
+ {
+ if (projNode == value)
+ return;
+
+ projNode = value;
+
+ NotifyValueChanged ("ProjectNode", projNode);
+
+ if (projNode == null)
+ return;
+
+ if (!File.Exists (projNode.AbsolutePath))
+ return;
+
+ parser = getParserFromExt (System.IO.Path.GetExtension (projNode.Extension));
+
+ try {
+ buffer.Load (projNode.Source);
+ oldSource = projNode.Source;
+ } catch (Exception ex) {
+ Debug.WriteLine (ex.ToString ());
+ }
+
+ updateMaxScrollY ();
+ MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns);
+ updatePrintedLines ();
+
+ RegisterForGraphicUpdate ();
+ }
+ }
+ [XmlAttributeAttribute][DefaultValue("BlueGray")]
+ public virtual Color SelectionBackground {
+ get { return selBackground; }
+ set {
+ if (value == selBackground)
+ return;
+ selBackground = value;
+ NotifyValueChanged ("SelectionBackground", selBackground);
+ RegisterForRedraw ();
+ }
+ }
+ [XmlAttributeAttribute][DefaultValue("White")]
+ public virtual Color SelectionForeground {
+ get { return selForeground; }
+ set {
+ if (value == selForeground)
+ return;
+ selForeground = value;
+ NotifyValueChanged ("SelectionForeground", selForeground);
+ RegisterForRedraw ();
+ }
+ }
+
+ // [XmlAttributeAttribute][DefaultValue(0)]
+// public int CurrentColumn{
+// get { return _currentCol; }
+//// set {
+//// if (value == _currentCol)
+//// return;
+//// if (value < 0)
+//// _currentCol = 0;
+//// else if (value > buffer[_currentLine].PrintableLength)
+//// _currentCol = buffer[_currentLine].PrintableLength;
+//// else
+//// _currentCol = value;
+////
+//// buffer.SetBufferPos (CurrentPosition);
+////
+//// if (_currentCol < ScrollX)
+//// ScrollX = _currentCol;
+//// else if (_currentCol >= ScrollX + visibleColumns)
+//// ScrollX = _currentCol - visibleColumns + 1;
+////
+//// NotifyValueChanged ("CurrentColumn", _currentCol);
+//// }
+// }
+// [XmlAttributeAttribute][DefaultValue(0)]
+// public int CurrentLine{
+// get { return _currentLine; }
+//// set {
+//// if (value == _currentLine)
+//// return;
+//// if (value >= buffer.LineCount)
+//// _currentLine = buffer.LineCount-1;
+//// else if (value < 0)
+//// _currentLine = 0;
+//// else
+//// _currentLine = value;
+////
+//// if (_currentCol > buffer[_currentLine].PrintableLength)
+//// CurrentColumn = buffer[_currentLine].PrintableLength;//buffer.setBufferPos is called inside
+//// else
+//// buffer.SetBufferPos (CurrentPosition);
+////
+////// if (_currentLine < ScrollY)
+////// ScrollY = _currentLine;
+////// else if (_currentLine >= ScrollY + visibleLines)
+////// ScrollY = _currentLine - visibleLines + 1;
+////
+//// NotifyValueChanged ("CurrentLine", _currentLine);
+//// }
+// }
+// /// <summary>
+// /// Current position is in the printed coord system, tabulation chars are replaced with 4 spaces,
+// /// while in the buffer, the position holds tabulations as single chars
+// /// </summary>
+// /// <value>The current position.</value>
+// [XmlIgnore]public Point CurrentPosition {
+// get { return new Point(CurrentColumn, CurrentLine); }
+// set {
+// _currentCol = value.X;
+// _currentLine = value.Y;
+//
+// if (_currentCol < ScrollX)
+// ScrollX = _currentCol;
+// else if (_currentCol >= ScrollX + visibleColumns)
+// ScrollX = _currentCol - visibleColumns + 1;
+////
+//// if (_currentLine < ScrollY)
+//// ScrollY = _currentLine;
+//// else if (_currentLine >= ScrollY + visibleLines)
+//// ScrollY = _currentLine - visibleLines + 1;
+//
+// NotifyValueChanged ("CurrentColumn", _currentCol);
+// NotifyValueChanged ("CurrentLine", _currentLine);
+// }
+// }
+
+// [XmlIgnore]public string SelectedText
+// {
+// get {
+// if (!selectionIsEmpty)
+// buffer.SetSelection (selectionStart, selectionEnd);
+// return buffer.SelectedText;
+// }
+// }
+
+ #endregion
+
+
+ void updateOnScreenCurLineFromBuffCurLine(){
+ printedCurrentLine = PrintedLines.IndexOf (buffer.CurrentCodeLine);
+ }
+
+// void setCurrentLineFromBuffer () {
+// _currentLine = buffer.CurrentLine;
+// NotifyValueChanged ("CurrentLine", _currentLine);
+// }
+
+ public override int ScrollY {
+ get {
+ return base.ScrollY;
+ }
+ set {
+ if (value == base.ScrollY)
+ return;
+ base.ScrollY = value;
+ updatePrintedLines ();
+ }
+ }
+
+
+ /// <summary>
+ /// Index of the currentline in the PrintedLines array
+ /// </summary>
+ int printedCurrentLine = 0;
+
+ /// <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.Height * 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.Height));
+ 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;
+ }
+ 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){
+ if (cl.IsFoldable) {
+ if (cl.SyntacticNode.StartLine != cl.SyntacticNode.EndLine) {
+ gr.SetSourceColor (Color.Black);
+ Rectangle rFld = new Rectangle (cb.X + leftMargin - leftMarginGap - foldSize, (int)(y + fe.Height / 2.0 - foldSize / 2.0), foldSize, foldSize);
+ 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);
+ }
+ 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);
+ }
+// 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.Height);
+// gr.LineTo (0.5 + cursorX, cb.Y + (printedCurrentLine + 1) * fe.Height);
+// 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.Height);
+ 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.Height);
+ 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.Height * 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 ();
+ }
+
+ int selStartCol;
+ int selEndCol;
+
+ protected override void onDraw (Context gr)
+ {
+// if (!System.Threading.Monitor.TryEnter (buffer.EditMutex)) {
+// RegisterForGraphicUpdate ();
+// return;
+// }
+
+ 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);
+
+ lock (buffer.EditMutex) {
+ #region draw text cursor
+ if (buffer.SelectionInProgress){
+ selStartCol = getTabulatedColumn (buffer.SelectionStart);
+ selEndCol = getTabulatedColumn (buffer.SelectionEnd);
+ }else if (HasFocus){
+ gr.LineWidth = 1.0;
+ double cursorX = cb.X + (getTabulatedColumn(buffer.CurrentPosition) - ScrollX) * fe.MaxXAdvance + leftMargin;
+ gr.MoveTo (0.5 + cursorX, cb.Y + (printedCurrentLine) * fe.Height);
+ gr.LineTo (0.5 + cursorX, cb.Y + (printedCurrentLine + 1) * fe.Height);
+ gr.Stroke();
+ }
+ #endregion
+
+ if (PrintedLines != null) {
+ for (int i = 0; i < visibleLines; i++) {
+ if (i + ScrollY >= buffer.UnfoldedLines)//TODO:need optimize
+ break;
+ drawLine (gr, cb, i);
+ }
+ }
+ }
+ //System.Threading.Monitor.Exit (buffer.EditMutex);
+ }
+ #endregion
+
+ #region Mouse handling
+ Point mouseLocalPos;
+ bool doubleClicked = false;
+
+ void updateCurrentPos(){
+// if (mouseLocalPos.X < 0)
+// CurrentColumn--;
+// else
+ PrintedCurrentLine = (int)Math.Max (0, Math.Floor (mouseLocalPos.Y / fe.Height));
+ 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;
+
+// if (mouseLocalPos.Y < 0)
+// ScrollY--;
+ }
+ 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;
+
+ 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
+ updateCurrentPos();
+ 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.Height))]));
+ return;
+ }
+
+ updateCurrentPos ();
+ 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;
+
+ 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:
+ buffer.Insert ("\t");
+ break;
+ case Key.F8:
+ toogleFolding (buffer.CurrentLine);
+// if (parser != null)
+// reparseSource ();
+ break;
+ default:
+ break;
+ }
+ RegisterForGraphicUpdate();
+ }
+ public override void onKeyPress (object sender, KeyPressEventArgs e)
+ {
+ base.onKeyPress (sender, e);
+
+ buffer.Insert (e.KeyChar.ToString());
+ buffer.ResetSelection ();
+
+ //RegisterForGraphicUpdate();
+ }
+ #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 Parser.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 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 : Parser
+ {
+ public new enum TokenType {
+ Unknown = Parser.TokenType.Unknown,
+ WhiteSpace = Parser.TokenType.WhiteSpace,
+ NewLine = Parser.TokenType.NewLine,
+ LineComment = Parser.TokenType.LineComment,
+ BlockCommentStart = Parser.TokenType.BlockCommentStart,
+ BlockComment = Parser.TokenType.BlockComment,
+ BlockCommentEnd = Parser.TokenType.BlockCommentEnd,
+ Affectation = Parser.TokenType.Affectation,
+ XMLDecl = Parser.TokenType.Preprocessor,
+ ElementStart,
+ ElementEnd,
+ ElementClosing = Parser.TokenType.StatementEnding,
+ ElementName = Parser.TokenType.Type,
+ AttributeName = Parser.TokenType.Identifier,
+ AttributeValueOpening = Parser.TokenType.StringLitteralOpening,
+ AttributeValueClosing = Parser.TokenType.StringLitteralClosing,
+ AttributeValue = Parser.TokenType.StringLitteral,
+ }
+
+ 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 (ParsingException 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 ParsingException (this, "Unexpected end of line");
+ Read ();
+ eol = true;
+ continue;
+ }
+
+ if (curState == States.BlockComment) {
+ if (currentTok != TokenType.Unknown)
+ Debugger.Break ();
+
+ currentTok.Start = CurrentPosition;
+ currentTok.Type = (Parser.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 ParsingException (this, "xml decl may appear only on first line");
+ readToCurrTok ();
+ currentTok += ReadLineUntil ("?>");
+ if (Peek (2) != "?>")
+ throw new ParsingException (this, "expecting '?>'");
+ readToCurrTok (2);
+ saveAndResetCurrentTok (TokenType.XMLDecl);
+ curState = States.prolog;
+ break;
+ case '!':
+ readToCurrTok ();
+ switch (Peek()) {
+ case '-':
+ readToCurrTok ();
+ if (Peek () != '-')
+ throw new ParsingException (this, "Expecting comment start tag");
+ readToCurrTok ();
+ currentTok += ReadLineUntil ("--");
+ if (Peek (3) == "-->") {
+ readToCurrTok (3);
+ }else
+ curState = States.BlockComment;
+ saveAndResetCurrentTok (TokenType.BlockComment);
+ break;
+ default:
+ throw new ParsingException(this, "error");
+ }
+ break;
+ default:
+ if (!(curState == States.Content || curState == States.XML || curState == States.init || curState == States.prolog))
+ throw new ParsingException (this, "Unexpected char: '<'");
+ if (Peek () == '/') {
+ curState = States.EndTag;
+ readToCurrTok ();
+ saveAndResetCurrentTok (TokenType.ElementEnd);
+ } else {
+ curState = States.StartTag;
+ saveAndResetCurrentTok (TokenType.ElementStart);
+ }
+
+ if (!nextCharIsValidCharStartName)
+ throw new ParsingException (this, "Expected element name");
+
+ readToCurrTok (true);
+ while (nextCharIsValidCharName)
+ readToCurrTok ();
+
+ saveAndResetCurrentTok (TokenType.ElementName);
+ break;
+ }
+ break;
+ case '/':
+ if (curState != States.StartTag)
+ throw new ParsingException (this, "Unexpected char: '/'");
+ readToCurrTok (true);
+ if (Peek () != '>')
+ throw new ParsingException (this, "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 ParsingException (this, "Unexpected char: '>'");
+ }
+ break;
+ default:
+ switch (curState) {
+ case States.StartTag:
+ if (!nextCharIsValidCharStartName)
+ throw new ParsingException (this, "Expected attribute name");
+ readToCurrTok (true);
+ while (nextCharIsValidCharName)
+ readToCurrTok ();
+ saveAndResetCurrentTok (TokenType.AttributeName);
+ if (Peek () != '=')
+ throw new ParsingException (this, "Expecting: '='");
+ readAndResetCurrentTok (TokenType.Affectation, true);
+
+ char openAttVal = Peek ();
+ if (openAttVal != '"' && openAttVal != '\'')
+ throw new ParsingException (this, "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 ParsingException (this, string.Format ("Expecting {0}", openAttVal));
+ readAndResetCurrentTok (TokenType.AttributeValueClosing, true);
+ break;
+ default:
+ throw new ParsingException (this, "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 ()
+ {
+ RootNode = new Node () { Name = "RootNode", Type="Root" };
+
+ 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++;
+ Node newElt = new Node () { Name = cl.Tokens [tokPtr].Content, StartLine = cl };
+ currentNode.AddChild (newElt);
+ currentNode = newElt;
+ if (cl.SyntacticNode == null)
+ cl.SyntacticNode = newElt;
+ 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 ParsingException (this, "Closing tag mismatch");
+ }
+ currentNode.EndLine = cl;
+ currentNode = currentNode.Parent;
+ break;
+ case TokenType.ElementClosing:
+ //currentNode = currentNode.Parent;
+ break;
+ default:
+ break;
+ }
+ tokPtr++;
+ }
+ }
+ }
+ }
+}
+
using System;
using Crow;
-namespace CrowIDE
+namespace Crow.Coding
{
public class VerticalLine : GraphicObject
{
</Menu>
<VerticalStack DataSource="{CurrentSolution}">
<HorizontalStack Height="80%">
- <EditPane SelectedItem="{²SelectedItem}" SelectedItemElement="{²SelectedItemElement}" Data="{OpenedItems}" DataTest="Extension"
- ItemTemplate="#CrowIDE.ui.EditPaneItems.template"/>
+ <EditPane SelectedItem="{SelectedItem}" SelectedItemElement="{²SelectedItemElement}" Data="{OpenedItems}" DataTest="Extension"
+ ItemTemplate="#Crow.Coding.ui.EditPaneItems.template"/>
<Splitter/>
<VerticalStack Width="30%">
<TreeView Name="treeview" Height="50%" IsRoot="true"
Data="{Projects}" SelectedItemChanged="onSelectedItemChanged"
- ItemTemplate="#CrowIDE.ui.ProjectTree.template"/>
+ ItemTemplate="#Crow.Coding.ui.ProjectTree.template"/>
<Splitter/>
<MembersView Instance="{SelectedItemElement}" DataTest="Type"
- ItemTemplate="#CrowIDE.ui.MembersItem.template"/>
+ ItemTemplate="#Crow.Coding.ui.MembersItem.template"/>
</VerticalStack>
</HorizontalStack>
<Splitter/>
<?xml version="1.0" encoding="UTF-8" ?>
-<TabView Name="ItemsContainer" Orientation="Horizontal" Spacing="24"/>
+<TabView SelectedTab="{./SelectedIndex}" Name="ItemsContainer" Orientation="Horizontal" Spacing="24"/>
<HorizontalStack Height="Stretched" >
<SourceEditor Focusable="true" Name="editor" Font="monospace, 12" VerticalAlignment="Top" Margin="10"
Foreground="Jet" Background="White" Width="Stretched" Height="Stretched"
- FilePath="{AbsolutePath}" KeyDown="textView_KeyDown"/>
+ ProjectNode="{}" KeyDown="textView_KeyDown"/>
<ScrollBar Name="scrollbarY" Value="{²../editor.ScrollY}"
LargeIncrement="{../editor.VisibleLines}"
CursorSize="{../editor.ChildHeightRatio}"
</HorizontalStack>
<ScrollBar Name="scrollbarX" Value="{²../editor.ScrollX}"
Maximum="{../editor.MaxScrollX}" Orientation="Horizontal"
- Height="14" />
+ Height="14" />
<HorizontalStack Height="Fit">
<GraphicObject Height="5" Width="Stretched"/>
- <GraphicObject Background="Red" Width="10" Height="10" Visible="{IsDirty}"/>
+ <GraphicObject Background="Red" Width="5" Height="5" Visible="{../../editor.IsDirty}"/>
<Label Text="column:"/>
<Label Text="{../../editor.CurrentColumn}"/>
<Label Text="Line:"/>
<Image Path="{AbsolutePath}"/>
</TabItem>
</ItemTemplate>
+<ItemTemplate DataType=".style" DataTest="Extension">
+ <TabItem Caption="{DisplayName}" QueryClose="OnQueryClose">
+ <HorizontalStack>
+ <Scroller Name="scroller1" Background="White"
+ Margin="2" VerticalScrolling="true" ScrollY="{../scrollbar1.Value}"
+ ValueChanged="./_scroller_ValueChanged">
+ <TextBox VerticalAlignment="Top"
+ Text="{²Source}" Multiline="true" TextAlignment="TopLeft"
+ Font="Courriernew 10"/>
+ </Scroller>
+ <ScrollBar Name="scrollbar1" Value="{../scroller1.ScrollY}"
+ LargeIncrement="{../scroller1.PageHeight}" SmallIncrement="30"
+ CursorSize="{../scroller1.ChildHeightRatio}"
+ Maximum="{../scroller1.MaximumScroll}" Orientation="Vertical"
+ Width="14" />
+ </HorizontalStack>
+ </TabItem>
+</ItemTemplate>
<ItemTemplate DataType=".crow" DataTest="Extension">
<TabItem Caption="{DisplayName}" QueryClose="OnQueryClose">
<VerticalStack>
<HorizontalStack Height="Stretched" >
<SourceEditor Focusable="true" Name="editor" Font="monospace, 11" VerticalAlignment="Top" Margin="10"
Foreground="Jet" Background="White" Width="Stretched" Height="Stretched"
- FilePath="{AbsolutePath}" KeyDown="textView_KeyDown"/>
+ ProjectNode="{}" KeyDown="textView_KeyDown"/>
<ScrollBar Name="scrollbarY" Value="{²../editor.ScrollY}"
LargeIncrement="{../editor.VisibleLines}"
CursorSize="{../editor.ChildHeightRatio}"
Maximum="{../editor.MaxScrollX}" Orientation="Horizontal"
Height="14" />
<HorizontalStack Height="Fit">
+ <Label DataSource="{../../crowContainer.IMLError}" Background="Red" Fit="true" Text="{Message}"/>
<GraphicObject Height="5" Width="Stretched"/>
- <GraphicObject Background="Red" Width="10" Height="10" Visible="{IsDirty}"/>
+ <GraphicObject Background="Red" Width="5" Height="5" Visible="{../../editor.IsDirty}"/>
<Label Text="column:"/>
<Label Text="{../../editor.CurrentColumn}"/>
<Label Text="Line:"/>
</HorizontalStack>
</ItemTemplate>
<ItemTemplate DataType="Crow.Group" Data="GetChildren"
- Path="#CrowIDE.ui.GTreeExpITemp.crow"/>
+ Path="#Crow.Coding.ui.GTreeExpITemp.crow"/>
<ItemTemplate DataType="Crow.Container" Data="GetChildren"
- Path="#CrowIDE.ui.GTreeExpITemp.crow"/>
+ Path="#Crow.Coding.ui.GTreeExpITemp.crow"/>
<ItemTemplate DataType="Crow.TemplatedContainer" Data="GetChildren"
- Path="#CrowIDE.ui.GTreeExpITemp.crow"/>
+ Path="#Crow.Coding.ui.GTreeExpITemp.crow"/>
<ItemTemplate DataType="Crow.TemplatedGroup" Data="GetChildren"
- Path="#CrowIDE.ui.GTreeExpITemp.crow"/>
+ Path="#Crow.Coding.ui.GTreeExpITemp.crow"/>
</TreeView>
</VerticalStack>
</Window>
<?xml version="1.0"?>
<Window Caption="Properties" Width="30%" Height="60%" AlwaysOnTop="true">
<MembersView Instance="{SelectedItem}" DataTest="Type"
- ItemTemplate="#CrowIDE.ui.MembersItem.template"/>
+ ItemTemplate="#Crow.Coding.ui.MembersItem.template"/>
</Window>
\ No newline at end of file
</HorizontalStack>
</VerticalStack>
<TreeView Width="50%" IsRoot="true" Name="treeView" Data="{RootItems}" DataTest="Type"
- ItemTemplate="#CrowIDE.ui.ProjectTree.template">
+ ItemTemplate="#Crow.Coding.ui.ProjectTree.template">
</TreeView>
</HorizontalStack>
</Window>
<ItemTemplate>
<Label Text="{}" Background="DarkRed" Foreground="White"/>
</ItemTemplate>
-<ItemTemplate DataType="CrowIDE.Project" Data="RootItems" DataTest="Type">
+<ItemTemplate DataType="Crow.Coding.Project" Data="RootItems" DataTest="Type">
<Expandable Caption="{Name}" ContextCommands="{Commands}" >
<Template>
<VerticalStack>
iRect = ifaceBounds;
CrowInterface = new Interface ();
+ CrowInterface.Init ();
#if MEASURE_TIME
PerfMeasures = new List<PerformanceMeasure> (
//if tab is used as a templated item root in a templatedGroup, local datasource
//is not null, in this case, removing the data entries will delete automatically the item
if (localDataSourceIsNull)
- (Parent as TabView).DeleteChild (this);
+ (Parent as TabView)?.DeleteChild (this);
}
#endregion
return new Instantiator (_iface, s);
}
} catch (Exception ex) {
- throw new Exception ("Error loading IML fragment:\n" + fragment + "\n", ex);
+ throw new Exception ("IML Error: " + ex.Message);
}
}
#endregion
FontRenderingOptions.SubpixelOrder = SubpixelOrder.Rgb;
}
public Interface(){
- CurrentInterface = this;
CultureInfo.DefaultThreadCurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
+ }
+ #endregion
+
+ public void Init () {
+ CurrentInterface = this;
loadStyling ();
findAvailableTemplates ();
initTooltip ();
initContextMenus ();
}
- #endregion
#region Static and constants
/// <summary>
public static int DeviceRepeatInterval = 40;
/// <summary>Tabulation size in Text controls</summary>
public static int TabSize = 4;
- public static string LineBreak = "\r\n";
+ public static string LineBreak = "\n";
/// <summary> Allow rendering of interface in development environment </summary>
public static bool DesignerMode = false;
/// <summary> Disable caching for a widget if this threshold is reached </summary>
.GetManifestResourceNames ()
.Where (r => r.EndsWith (".style", StringComparison.OrdinalIgnoreCase))) {
using (Stream stream = assembly.GetManifestResourceStream (s)) {
- new StyleReader (this, stream, s);
+ new StyleReader (this.Styling, stream, s);
}
}
/// Resource ID must be 'fullClassName.template' (not case sensitive)
/// Those found in application assembly have priority to the default Crow's one
/// </summary>
- public Dictionary<string, string> DefaultTemplates = new Dictionary<string, string>();
+ public Dictionary<string, string> DefaultTemplates;
/// <summary>Finds available default templates at startup</summary>
void findAvailableTemplates(){
+ DefaultTemplates = new Dictionary<string, string>();
searchTemplatesOnDisk ("./");
string defTemplatePath = System.IO.Path.Combine (CrowConfigRoot, "defaultTemplates");
searchTemplatesOnDisk (defTemplatePath);
/// </summary>
/// <returns>new instance of graphic object created</returns>
/// <param name="path">path of the iml file to load</param>
- public GraphicObject Load (string path)
+ public virtual GraphicObject Load (string path)
{
//try {
return GetInstantiator (path).CreateInstance ();
/// </summary>
/// <returns>new Instantiator</returns>
/// <param name="path">path of the iml file to load</param>
- public Instantiator GetInstantiator(string path){
+ public virtual Instantiator GetInstantiator(string path){
if (!Instantiators.ContainsKey(path))
Instantiators [path] = new Instantiator(this, path);
return Instantiators [path];
/// try to fetch the requested one in the cache or create it.
/// They have additional properties for recursivity and
/// custom display per item type</summary>
- public ItemTemplate GetItemTemplate(string path){
+ public virtual ItemTemplate GetItemTemplate(string path){
if (!Instantiators.ContainsKey(path))
Instantiators [path] = new ItemTemplate(this, path);
return Instantiators [path] as ItemTemplate;
GraphicObject ToolTipContainer = null;
volatile bool tooltipVisible = false;
- void initTooltip () {
+ protected void initTooltip () {
ToolTipContainer = Load ("#Crow.Tooltip.template");
Thread t = new Thread (toolTipThreadFunc);
t.IsBackground = true;
#region Contextual menu
MenuItem ctxMenuContainer;
- void initContextMenus (){
+ protected void initContextMenus (){
ctxMenuContainer = Load ("#Crow.ContextMenu.template") as MenuItem;
}
int column = 1;
int line = 1;
- public StyleReader (Interface iface, Stream stream, string resId)
+ public StyleReader (Dictionary<string, Style> styling, Stream stream, string resId)
: base(stream)
{
resourceId = resId;
string expression = token.Trim ();
foreach (string tc in targetsClasses) {
- if (!iface.Styling.ContainsKey (tc))
- iface.Styling [tc] = new Style ();
- else if (iface.Styling [tc].ContainsKey (currentProperty))
+ if (!styling.ContainsKey (tc))
+ styling [tc] = new Style ();
+ else if (styling [tc].ContainsKey (currentProperty))
continue;
- iface.Styling [tc] [currentProperty] = expression;
+ styling [tc] [currentProperty] = expression;
}
token = "";
}