From 446a51f911c731eeb7a3b50987c59a7cd1316f78 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Philippe=20Bruy=C3=A8re?= Date: Thu, 13 Dec 2018 18:31:05 +0100 Subject: [PATCH] some caching for reflexion, other debug --- Crow.NetStd.sln | 20 +- Crow.sln | 26 +- Crow/Crow.csproj | 12 +- Crow/src/CompilerServices/CompilerServices.cs | 122 ++- Crow/src/GraphicObjects/GraphicObject.cs | 5 +- Crow/src/GraphicObjects/TemplatedGroup.cs | 23 +- Crow/src/Instantiator.cs | 16 +- Crow/src/Interface.cs | 26 +- Crow/src/ItemTemplate.cs | 40 +- Crow/src/backends/xcb/XCBBackend.cs | 17 +- Crow/src/{ => backends/xcb}/XCursor.cs | 0 CrowIDE/CrowIDE.NetStd.csproj | 5 +- CrowIDE/CrowIDE.csproj | 65 +- CrowIDE/src/CrowIDE.cs | 11 +- CrowIDE/src/Project.cs | 961 +++++++++--------- CrowIDE/src/ProjectTree/CSProjectFile.cs | 72 ++ CrowIDE/src/ProjectTree/ProjectFile.cs | 12 +- CrowIDE/ui/DockWindows/GTreeExpITemp.crow | 6 +- CrowIDE/ui/DockWindows/winGTExplorer.crow | 2 +- Tests/Tests.NetStd.csproj | 5 +- Tests/Tests.csproj | 129 ++- Tests/testClass.cs | 25 + Tests/ui/TreeExpandable.template | 30 + 23 files changed, 907 insertions(+), 723 deletions(-) rename Crow/src/{ => backends/xcb}/XCursor.cs (100%) create mode 100644 CrowIDE/src/ProjectTree/CSProjectFile.cs create mode 100644 Tests/testClass.cs create mode 100644 Tests/ui/TreeExpandable.template diff --git a/Crow.NetStd.sln b/Crow.NetStd.sln index c12c637c..a62e1600 100644 --- a/Crow.NetStd.sln +++ b/Crow.NetStd.sln @@ -27,28 +27,12 @@ Global {75BDE4C7-4BAF-4A03-B697-5D1370775E20}.Release|Any CPU.ActiveCfg = Release|Any CPU {75BDE4C7-4BAF-4A03-B697-5D1370775E20}.Release|Any CPU.Build.0 = Release|Any CPU {28BAF8B8-6A6E-40D5-8E9C-E7C1165C59DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {28BAF8B8-6A6E-40D5-8E9C-E7C1165C59DD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {28BAF8B8-6A6E-40D5-8E9C-E7C1165C59DD}.Debug|x64.ActiveCfg = Debug|Any CPU - {28BAF8B8-6A6E-40D5-8E9C-E7C1165C59DD}.Debug|x64.Build.0 = Debug|Any CPU - {28BAF8B8-6A6E-40D5-8E9C-E7C1165C59DD}.Debug|x86.ActiveCfg = Debug|Any CPU - {28BAF8B8-6A6E-40D5-8E9C-E7C1165C59DD}.Debug|x86.Build.0 = Debug|Any CPU {28BAF8B8-6A6E-40D5-8E9C-E7C1165C59DD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {28BAF8B8-6A6E-40D5-8E9C-E7C1165C59DD}.Debug|Any CPU.Build.0 = Debug|Any CPU {28BAF8B8-6A6E-40D5-8E9C-E7C1165C59DD}.Release|Any CPU.Build.0 = Release|Any CPU - {28BAF8B8-6A6E-40D5-8E9C-E7C1165C59DD}.Release|x64.ActiveCfg = Release|Any CPU - {28BAF8B8-6A6E-40D5-8E9C-E7C1165C59DD}.Release|x64.Build.0 = Release|Any CPU - {28BAF8B8-6A6E-40D5-8E9C-E7C1165C59DD}.Release|x86.ActiveCfg = Release|Any CPU - {28BAF8B8-6A6E-40D5-8E9C-E7C1165C59DD}.Release|x86.Build.0 = Release|Any CPU {A01B3151-BC81-437C-B526-CC8DBB808638}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A01B3151-BC81-437C-B526-CC8DBB808638}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A01B3151-BC81-437C-B526-CC8DBB808638}.Debug|x64.ActiveCfg = Debug|Any CPU - {A01B3151-BC81-437C-B526-CC8DBB808638}.Debug|x64.Build.0 = Debug|Any CPU - {A01B3151-BC81-437C-B526-CC8DBB808638}.Debug|x86.ActiveCfg = Debug|Any CPU - {A01B3151-BC81-437C-B526-CC8DBB808638}.Debug|x86.Build.0 = Debug|Any CPU {A01B3151-BC81-437C-B526-CC8DBB808638}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A01B3151-BC81-437C-B526-CC8DBB808638}.Debug|Any CPU.Build.0 = Debug|Any CPU {A01B3151-BC81-437C-B526-CC8DBB808638}.Release|Any CPU.Build.0 = Release|Any CPU - {A01B3151-BC81-437C-B526-CC8DBB808638}.Release|x64.ActiveCfg = Release|Any CPU - {A01B3151-BC81-437C-B526-CC8DBB808638}.Release|x64.Build.0 = Release|Any CPU - {A01B3151-BC81-437C-B526-CC8DBB808638}.Release|x86.ActiveCfg = Release|Any CPU - {A01B3151-BC81-437C-B526-CC8DBB808638}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/Crow.sln b/Crow.sln index a992af34..68347c39 100644 --- a/Crow.sln +++ b/Crow.sln @@ -30,22 +30,30 @@ Global 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 diff --git a/Crow/Crow.csproj b/Crow/Crow.csproj index 656c9da9..ade2082c 100644 --- a/Crow/Crow.csproj +++ b/Crow/Crow.csproj @@ -62,7 +62,6 @@ --> - @@ -179,5 +178,16 @@ PreserveNewest + + + + + + + + + + + diff --git a/Crow/src/CompilerServices/CompilerServices.cs b/Crow/src/CompilerServices/CompilerServices.cs index 5112fb12..ceb09c1a 100644 --- a/Crow/src/CompilerServices/CompilerServices.cs +++ b/Crow/src/CompilerServices/CompilerServices.cs @@ -33,12 +33,23 @@ using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Xml; using Crow.IML; - +using System.Text; namespace Crow.IML { public static class CompilerServices { + /// + /// known types cache, prevent rewalking all the assemblies of the domain + /// the key is the type simple name + /// + internal static Dictionary knownTypes = new Dictionary (); + /// + /// known extension methods. + /// key is type dot memberName. + /// + internal static Dictionary knownExtMethods = new Dictionary (); + internal static Type TObject = typeof(object); internal static MethodInfo stringEquals = typeof (string).GetMethod("Equals", new Type [3] { typeof (string), typeof (string), typeof (StringComparison) }); internal static MethodInfo miObjToString = typeof(object).GetMethod("ToString"); @@ -405,20 +416,57 @@ namespace Crow.IML return query; } /// - /// search for extentions method in entry assembly then in crow assembly + /// search for extentions method in entry assembly then in assembly where the type is defined /// /// Extention MethodInfo /// Extended type /// Extention method name - internal static MethodInfo SearchExtMethod(Type t, string methodName){ + //internal static MethodInfo SearchExtMethod(Type t, string methodName){ + // MethodInfo mi = null; + // mi = GetExtensionMethods (Assembly.GetEntryAssembly(), t) + // .Where (em => em.Name == methodName).FirstOrDefault (); + // if (mi != null) + // return mi; + + // return GetExtensionMethods (t.Module.Assembly, t) + // .Where (em => em.Name == methodName).FirstOrDefault (); + //} + internal static MethodInfo SearchExtMethod (Type t, string methodName) + { + string key = t.Name + "." + methodName; + if (knownExtMethods.ContainsKey (key)) + return knownExtMethods [key]; + + //Console.WriteLine ($"*** search extension method: {t};{methodName} => key={key}"); + MethodInfo mi = null; - mi = GetExtensionMethods (Assembly.GetEntryAssembly(), t) - .Where (em => em.Name == methodName).FirstOrDefault (); - if (mi != null) - return mi; + mi = GetExtensionMethods2 (Assembly.GetEntryAssembly (), t, methodName); + if (mi == null) + mi = GetExtensionMethods2 (t.Module.Assembly, t, methodName); - return GetExtensionMethods (Assembly.GetExecutingAssembly(), t) - .Where (em => em.Name == methodName).FirstOrDefault (); + //add key even if mi is null to prevent searching again and again for propertyless bindings + knownExtMethods.Add (key, mi); + return mi; + } + + static MethodInfo GetExtensionMethods2 (Assembly assembly, Type extendedType, string methodName) + { + foreach (Type t in assembly.GetTypes ().Where + (ty => ty.IsDefined (typeof (ExtensionAttribute), false))) { + foreach (MethodInfo mi in t.GetMethods + (BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).Where + (m=> m.Name == methodName && m.IsDefined (typeof (ExtensionAttribute), false) && + m.GetParameters ().Length == 1)) { + Type curType = extendedType; + while (curType != null) { + if (mi.GetParameters () [0].ParameterType == curType) + return mi; + curType = curType.BaseType; + } + } + + } + return null; } /// /// retrieve event handler in class or ancestors @@ -893,20 +941,32 @@ namespace Crow.IML /// /// the corresponding type object if found /// type name - internal static Type tryGetType (string strDataType){ + internal static Type getTypeFromName (string strDataType){ + if (knownTypes.ContainsKey (strDataType)) + return knownTypes [strDataType]; Type dataType = Type.GetType(strDataType); - if (dataType != null) + if (dataType != null) { + knownTypes.Add (strDataType, dataType); return dataType; - Assembly a = Assembly.GetEntryAssembly (); - foreach (Type expT in a.GetExportedTypes ()) { - if (expT.Name == strDataType) - return dataType; } + foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies ()) { + if (a.IsDynamic) + continue; + foreach (Type expT in a.GetExportedTypes ()) { + if (expT.Name != strDataType) + continue; + knownTypes.Add (strDataType, expT); + return expT; + } + } + knownTypes.Add (strDataType, null); return null; } + //get value from member of object internal static object getDataTypeAndFetch (object data, string fetchMethod){ Type dataType = data.GetType(); + //Console.WriteLine ($"get data type and fetch {data}.{fetchMethod}"); MethodInfo miGetDatas = dataType.GetMethod (fetchMethod, new Type[] {}); if (miGetDatas == null) miGetDatas = CompilerServices.SearchExtMethod (dataType, fetchMethod); @@ -923,8 +983,36 @@ namespace Crow.IML if (miGetDatas == null) throw new Exception ("Read only property for fetching data in ItemTemplate: " + fetchMethod); } - object tmp = miGetDatas.Invoke (data, null); - return tmp; + return miGetDatas.IsStatic ? + miGetDatas.Invoke (null, new object [] { data }) : miGetDatas.Invoke (data, null); + } + //TODO:memberinfo found here must be cached + internal static object getValue (Type dataType, object data, string member) + { + //Console.WriteLine ($"get value: {dataType} ; {data} ; {member}"); + + MethodInfo miGetDatas = dataType.GetMethod (member, new Type [] { }); + if (miGetDatas != null) + return miGetDatas.Invoke (data, null); + MemberInfo mbi = dataType.GetMember (member).FirstOrDefault (); + if (mbi == null) { + MethodInfo miExt = CompilerServices.SearchExtMethod (dataType, member); + if (miExt == null)//and among fields + throw new Exception ($"member {member} not found in {dataType}"); + return miExt.Invoke (null, new object [] { data }); + } + if (mbi.MemberType == MemberTypes.Property) { + miGetDatas = (mbi as PropertyInfo)?.GetGetMethod (); + if (miGetDatas == null) + throw new Exception ($"no getter found for property {member} in {dataType}"); + return miGetDatas.Invoke (data, null); + } + + FieldInfo fi = mbi as FieldInfo; + if (fi == null) + throw new Exception ($"member {member} not found in {dataType}"); + + return fi.GetValue (data); } } } diff --git a/Crow/src/GraphicObjects/GraphicObject.cs b/Crow/src/GraphicObjects/GraphicObject.cs index fb4f6393..b43ae54a 100644 --- a/Crow/src/GraphicObjects/GraphicObject.cs +++ b/Crow/src/GraphicObjects/GraphicObject.cs @@ -149,7 +149,10 @@ namespace Crow } } return di; - } + } + public string DesignName { + get { return GetType ().Name + design_id; } + } #endif #region IDisposable implementation diff --git a/Crow/src/GraphicObjects/TemplatedGroup.cs b/Crow/src/GraphicObjects/TemplatedGroup.cs index dd9afb6c..29056a50 100644 --- a/Crow/src/GraphicObjects/TemplatedGroup.cs +++ b/Crow/src/GraphicObjects/TemplatedGroup.cs @@ -411,13 +411,7 @@ namespace Crow loadingTime.ElapsedMilliseconds, this.ToString()); #endif } - string getItempKey(Type dataType, object o, string propertyName){ - try { - return dataType.GetProperty (propertyName).GetGetMethod ().Invoke (o, null)?.ToString(); - } catch { - return dataType.FullName; - } - } + protected void loadItem(object o, Group page, string _dataTest){ if (o == null)//TODO:surely a threading sync problem return; @@ -426,14 +420,23 @@ namespace Crow Type dataType = o.GetType (); string itempKey = dataType.FullName; - if (_dataTest != "TypeOf") - itempKey = getItempKey (dataType, o, _dataTest); + //if item template selection is not done depending on the type of item + //dataTest must contains a member name of the item + if (_dataTest != "TypeOf") { + try { + itempKey = CompilerServices.getValue (dataType, o, _dataTest)?.ToString (); + } catch { + itempKey = dataType.FullName; + } + } if (ItemTemplates.ContainsKey (itempKey)) iTemp = ItemTemplates [itempKey]; else { foreach (string it in ItemTemplates.Keys) { - Type t = CompilerServices.tryGetType (it); + if (it == "default") + continue; + Type t = CompilerServices.getTypeFromName (it); if (t == null) continue; if (t.IsAssignableFrom (dataType)) {//TODO:types could be cached diff --git a/Crow/src/Instantiator.cs b/Crow/src/Instantiator.cs index 4f9ee733..f42d1f13 100644 --- a/Crow/src/Instantiator.cs +++ b/Crow/src/Instantiator.cs @@ -68,6 +68,8 @@ namespace Crow.IML } #endregion + internal static Dictionary knownGOTypes = new Dictionary (); + public Type RootType; InstanciatorInvoker loader; protected Interface iface; @@ -1183,15 +1185,21 @@ namespace Crow.IML /// the corresponding type object /// graphic object type name without its namespace Type tryGetGOType (string typeName){ + if (knownGOTypes.ContainsKey (typeName)) + return knownGOTypes [typeName]; Type t = Type.GetType ("Crow." + typeName); - if (t != null) - return t; + if (t != null) { + knownGOTypes.Add (typeName, t); + return t; + } foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) { if (a.IsDynamic) continue; foreach (Type expT in a.GetExportedTypes ()) { - if (expT.Name == typeName) - return expT; + if (expT.Name != typeName) + continue; + knownGOTypes.Add (typeName, expT); + return expT; } } return null; diff --git a/Crow/src/Interface.cs b/Crow/src/Interface.cs index 1dfcfee2..f53a2769 100644 --- a/Crow/src/Interface.cs +++ b/Crow/src/Interface.cs @@ -24,10 +24,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; using System.Linq; using System.Reflection; using System.Threading; @@ -37,7 +33,10 @@ using Cairo; using System.Globalization; using Crow.IML; using System.Runtime.InteropServices; - +using System; +using System.IO; +using System.Diagnostics; +using System.Collections.Generic; namespace Crow @@ -412,18 +411,7 @@ namespace Crow } } - void loadCursors(){ - //Load cursors - XCursor.Cross = XCursorFile.Load(this, "#Crow.Images.Icons.Cursors.cross").Cursors[0]; - XCursor.Default = XCursorFile.Load(this, "#Crow.Images.Icons.Cursors.arrow").Cursors[0]; - XCursor.NW = XCursorFile.Load(this, "#Crow.Images.Icons.Cursors.top_left_corner").Cursors[0]; - XCursor.NE = XCursorFile.Load(this, "#Crow.Images.Icons.Cursors.top_right_corner").Cursors[0]; - XCursor.SW = XCursorFile.Load(this, "#Crow.Images.Icons.Cursors.bottom_left_corner").Cursors[0]; - XCursor.SE = XCursorFile.Load(this, "#Crow.Images.Icons.Cursors.bottom_right_corner").Cursors[0]; - XCursor.H = XCursorFile.Load(this, "#Crow.Images.Icons.Cursors.sb_h_double_arrow").Cursors[0]; - XCursor.V = XCursorFile.Load(this, "#Crow.Images.Icons.Cursors.sb_v_double_arrow").Cursors[0]; - XCursor.Text = XCursorFile.Load(this, "#Crow.Images.Icons.Cursors.ibeam").Cursors[0]; - } + #endregion #region Templates @@ -499,10 +487,10 @@ namespace Crow string resId = path.Substring (1); //try/catch added to prevent nunit error try { - stream = System.Reflection.Assembly.GetEntryAssembly ().GetManifestResourceStream (resId); + stream = Assembly.GetEntryAssembly ().GetManifestResourceStream (resId); } catch{} if (stream == null)//try to find ressource in Crow assembly - stream = System.Reflection.Assembly.GetExecutingAssembly ().GetManifestResourceStream (resId); + stream = Assembly.GetExecutingAssembly ().GetManifestResourceStream (resId); if (stream == null) throw new Exception("Resource not found: " + path); diff --git a/Crow/src/ItemTemplate.cs b/Crow/src/ItemTemplate.cs index 05d7c268..e42c7540 100644 --- a/Crow/src/ItemTemplate.cs +++ b/Crow/src/ItemTemplate.cs @@ -143,19 +143,10 @@ namespace Crow /// /// Host. public void CreateExpandDelegate (TemplatedGroup host){ - Type dataType = null; - //if (host.DataTest == "TypeOf"){ - dataType = CompilerServices.tryGetType(strDataType); -// if (dataType == null) { -// Debug.WriteLine ("ItemTemplate error: DataType not found: {0}.", strDataType); -// return; -// } -// } + Type dataType = CompilerServices.getTypeFromName(strDataType); Type tmpGrpType = typeof(TemplatedGroup); Type evtType = typeof(EventHandler); - //PropertyInfo piData = tmpGrpType.GetProperty ("Data"); - MethodInfo evtInvoke = evtType.GetMethod ("Invoke"); ParameterInfo [] evtParams = evtInvoke.GetParameters (); Type handlerArgsType = evtParams [1].ParameterType; @@ -195,28 +186,11 @@ namespace Crow il.Emit (OpCodes.Ldarg_1); il.Emit (OpCodes.Call, CompilerServices.miIsAlreadyExpanded); il.Emit (OpCodes.Brtrue, gotoEnd); -// il.Emit (OpCodes.Ldloc_0); -// il.Emit (OpCodes.Callvirt, piData.GetGetMethod ()); -// il.Emit (OpCodes.Brfalse, ifDataIsNull); -// il.Emit (OpCodes.Br, gotoEnd); - -// il.MarkLabel(ifDataIsNull); - - //copy the ref of ItemTemplates list TODO: maybe find another way to share it among the nodes? -// FieldInfo fiTemplates = tmpGrpType.GetField("ItemTemplates"); -// il.Emit (OpCodes.Ldloc_0); -// il.Emit (OpCodes.Ldarg_0); -// il.Emit (OpCodes.Ldfld, fiTemplates); -// il.Emit (OpCodes.Stfld, fiTemplates); - - //call 'fetchMethodName' from the dataSource to build the sub nodes list - //il.Emit (OpCodes.Ldarg_0);//load root templatedGroop + //get the dataSource of the sender il.Emit (OpCodes.Ldarg_0);//push root TemplatedGroup into the stack il.Emit (OpCodes.Ldarg_1);//load sender node of expand - il.Emit (OpCodes.Callvirt, CompilerServices.miGetDataSource);//get the dataSource of the sender - - + il.Emit (OpCodes.Callvirt, CompilerServices.miGetDataSource); if (fetchMethodName != "self") {//special keyword self allows the use of recurent list<<< if (dataType == null) { @@ -292,9 +266,11 @@ namespace Crow if (miGetDatas == null) throw new Exception ("Write only property for fetching data in ItemTemplate: " + fetchMethodName); } - - il.Emit (OpCodes.Callvirt, miGetDatas); - } + if (miGetDatas.IsStatic) + il.Emit (OpCodes.Call, miGetDatas); + else + il.Emit (OpCodes.Callvirt, miGetDatas); + } diff --git a/Crow/src/backends/xcb/XCBBackend.cs b/Crow/src/backends/xcb/XCBBackend.cs index a3ccab91..b4199968 100644 --- a/Crow/src/backends/xcb/XCBBackend.cs +++ b/Crow/src/backends/xcb/XCBBackend.cs @@ -414,8 +414,9 @@ namespace Crow.XCB xcb_flush (conn); - IntPtr visual = findVisual (scr_it, scr.root_visual); + IntPtr visual = findVisual (scr_it, scr.root_visual); + //loadCursors (); iFace.surf = new Cairo.XcbSurface (conn, win, visual, iFace.ClientRectangle.Width, iFace.ClientRectangle.Height); } @@ -483,6 +484,20 @@ namespace Crow.XCB } #endregion + void loadCursors () + { + //Load cursors + XCursor.Cross = XCursorFile.Load (iFace, "#Crow.Images.Icons.Cursors.cross").Cursors [0]; + XCursor.Default = XCursorFile.Load (iFace, "#Crow.Images.Icons.Cursors.arrow").Cursors [0]; + XCursor.NW = XCursorFile.Load (iFace, "#Crow.Images.Icons.Cursors.top_left_corner").Cursors [0]; + XCursor.NE = XCursorFile.Load (iFace, "#Crow.Images.Icons.Cursors.top_right_corner").Cursors [0]; + XCursor.SW = XCursorFile.Load (iFace, "#Crow.Images.Icons.Cursors.bottom_left_corner").Cursors [0]; + XCursor.SE = XCursorFile.Load (iFace, "#Crow.Images.Icons.Cursors.bottom_right_corner").Cursors [0]; + XCursor.H = XCursorFile.Load (iFace, "#Crow.Images.Icons.Cursors.sb_h_double_arrow").Cursors [0]; + XCursor.V = XCursorFile.Load (iFace, "#Crow.Images.Icons.Cursors.sb_v_double_arrow").Cursors [0]; + XCursor.Text = XCursorFile.Load (iFace, "#Crow.Images.Icons.Cursors.ibeam").Cursors [0]; + } + static IntPtr findVisual (xcb_iterator_t scr_it, xcb_visualid_t visualId){ for (; scr_it.rem > 0; xcb_screen_next (ref scr_it)) { xcb_iterator_t depth_it = xcb_screen_allowed_depths_iterator (scr_it.data); diff --git a/Crow/src/XCursor.cs b/Crow/src/backends/xcb/XCursor.cs similarity index 100% rename from Crow/src/XCursor.cs rename to Crow/src/backends/xcb/XCursor.cs diff --git a/CrowIDE/CrowIDE.NetStd.csproj b/CrowIDE/CrowIDE.NetStd.csproj index 22e65166..0872a62d 100644 --- a/CrowIDE/CrowIDE.NetStd.csproj +++ b/CrowIDE/CrowIDE.NetStd.csproj @@ -23,9 +23,11 @@ + + - + @@ -45,7 +47,6 @@ - diff --git a/CrowIDE/CrowIDE.csproj b/CrowIDE/CrowIDE.csproj index ee755f6c..59b33cee 100644 --- a/CrowIDE/CrowIDE.csproj +++ b/CrowIDE/CrowIDE.csproj @@ -11,14 +11,9 @@ CrowIDE $(SolutionDir)build/$(Configuration) $(SolutionDir)build/obj/$(Configuration) - - - - - 0.8.0 Crow.Coding.CrowIDE - v4.5.2 + v4.6.1 true @@ -40,24 +35,7 @@ $(SolutionDir)build\obj\$(Configuration) $(SolutionDir)build\$(Configuration) - - Program - %24{TargetName} - %24{SolutionDir}\build\%24{ProjectConfigName} - false - - - Program - %24{TargetName} - %24{SolutionDir}\build\%24{ProjectConfigName} - false - - - Program - %24{TargetName} - %24{SolutionDir}\build\%24{ProjectConfigName} - false - + @@ -72,44 +50,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/CrowIDE/src/CrowIDE.cs b/CrowIDE/src/CrowIDE.cs index 9d643a9a..b5752ac0 100644 --- a/CrowIDE/src/CrowIDE.cs +++ b/CrowIDE/src/CrowIDE.cs @@ -77,8 +77,8 @@ namespace Crow.Coding CMDViewStyling = new Command(new Action(() => loadWindow ("#Crow.Coding.ui.DockWindows.winStyleView.crow",this))) { Caption = "Styling Explorer", CanExecute = true}; - CMDViewGTExp = new Command(new Action(() => loadWindow ("#Crow.Coding.ui.DockWindows.winGTExplorer.crow"))) - { Caption = "Graphic Tree Explorer", CanExecute = false}; + CMDViewGTExp = new Command(new Action(() => loadWindow ("#Crow.Coding.ui.DockWindows.winGTExplorer.crow",this))) + { Caption = "Graphic Tree Explorer", CanExecute = true}; CMDCompile = new Command(new Action(() => compileSolution())) { Caption = "Compile", CanExecute = false}; CMDViewProjProps = new Command(new Action(loadProjProps)) @@ -157,12 +157,7 @@ namespace Crow.Coding void initIde() { - foreach (string s in System.Reflection.Assembly.GetEntryAssembly().GetManifestResourceNames()) - { - Console.WriteLine(s); - } - - initCommands (); + initCommands (); GraphicObject go = AddWidget (@"#Crow.Coding.ui.CrowIDE.crow"); go.DataSource = this; diff --git a/CrowIDE/src/Project.cs b/CrowIDE/src/Project.cs index 0a653498..407f60b3 100644 --- a/CrowIDE/src/Project.cs +++ b/CrowIDE/src/Project.cs @@ -33,484 +33,487 @@ using System.CodeDom.Compiler; using Crow; using System.Text.RegularExpressions; -namespace Crow.Coding -{ - public class Project: IValueChange - { - #region IValueChange implementation - public event EventHandler ValueChanged; - public virtual void NotifyValueChanged(string MemberName, object _value) - { - ValueChanged.Raise(this, new ValueChangeEventArgs(MemberName, _value)); - } - #endregion - - bool isLoaded = false; - bool isExpanded; - XmlDocument xmlDoc; - XmlNode nodeProject; - XmlNode nodeProps; - XmlNodeList nodesItems; - SolutionProject solutionProject; - Crow.Command cmdSave, cmdOpen, cmdCompile, cmdSetAsStartProj, cmdNewFile; - - #region CTOR - public Project (Solution sol, SolutionProject sp) { - solutionProject = sp; - - solution = sol; - - cmdSave = new Crow.Command (new Action (() => Save ())) - { Caption = "Save", Icon = new SvgPicture ("#icons.save.svg"), CanExecute = true }; - cmdOpen = new Crow.Command (new Action (() => Load ())) - { Caption = "Open", Icon = new SvgPicture ("#icons.open.svg"), CanExecute = false }; - cmdCompile = new Crow.Command (new Action (() => Compile ())) { - Caption = "Compile", - Icon = "#icons.compile.svg" - }; - cmdSetAsStartProj = new Crow.Command (new Action (() => setAsStartupProject ())) { - Caption = "Set as Startup Project" - }; - cmdNewFile = new Crow.Command (new Action (() => AddNewFile ())) { - Caption = "Add New File", Icon = new SvgPicture ("#icons.blank-file.svg"), CanExecute = true - }; - - Commands = new List (new Crow.Command[] {cmdOpen,cmdSave,cmdSetAsStartProj,cmdCompile,cmdNewFile}); - - Load (); - } - #endregion - - public Solution solution; - public List Commands; - public CompilerResults CompilationResults; - public List dependantProjects = new List(); - public Project ParentProject = null; - List rootItems; - List flattenNodes; - - public string Name { - get { return solutionProject.ProjectName; } - } - public bool IsLoaded { - get { return isLoaded; } - set { - if (isLoaded == value) - return; - isLoaded = value; - NotifyValueChanged ("IsLoaded", isLoaded); - } - } - public bool IsExpanded - { - get { return isExpanded; } - set - { - if (value == isExpanded) - return; - isExpanded = value; - NotifyValueChanged ("IsExpanded", isExpanded); - } - } - public bool IsStartupProject { - get { return solution.StartupProject == this; } - } - public string Path { - get { return System.IO.Path.Combine (solution.SolutionFolder, solutionProject.RelativePath.Replace('\\','/')); } - } - public string RootDir { - get { return System.IO.Path.GetDirectoryName (Path); } - } - - - - public List RootItems { - get { return rootItems; } - } - - void buildTreeNodes(){ - ProjectNode root = new ProjectNode (this, ItemType.VirtualGroup, RootNamespace); - List items = new List (); - foreach (XmlNode i in nodesItems) { - foreach (XmlNode f in i.ChildNodes) { - items.Add (new ProjectItem (this, f)); - } - } - - flattenNodes = new List (); - - ProjectNode refs = new ProjectNode (this, ItemType.ReferenceGroup, "References"); - root.AddChild (refs); - - foreach (ProjectItem pn in items) { - switch (pn.Type) { - case ItemType.Reference: - refs.AddChild (pn); - flattenNodes.Add (pn); - break; - case ItemType.ProjectReference: - ProjectReference pr = new ProjectReference (pn); - refs.AddChild (pr); - flattenNodes.Add (pr); - break; - case ItemType.Compile: - case ItemType.None: - case ItemType.EmbeddedResource: - ProjectNode curNode = root; - string[] folds = pn.Path.Split ('/'); - for (int i = 0; i < folds.Length - 1; i++) { - ProjectNode nextNode = curNode.ChildNodes.FirstOrDefault (n => n.DisplayName == folds [i] && n.Type == ItemType.VirtualGroup); - if (nextNode == null) { - nextNode = new ProjectNode (this, ItemType.VirtualGroup, folds [i]); - curNode.AddChild (nextNode); - } - curNode = nextNode; - } - ProjectNode f = null; - switch (pn.Extension) { - case ".crow": - case ".template": - case ".goml": - case ".itemp": - case ".imtl": - f = new ImlProjectItem (pn); - break; - case ".style": - f = new StyleProjectItem (pn); - break; - default: - f = new ProjectFile (pn); - break; - } - curNode.AddChild (f); - flattenNodes.Add (f); - break; - } - } - root.SortChilds (); - - rootItems = root.ChildNodes; - } - - #region Project properties - public string ToolsVersion { - get { return nodeProject?.Attributes ["ToolsVersion"]?.Value; } - } - public string DefaultTargets { - get { return nodeProject?.Attributes ["DefaultTargets"]?.Value; } - } - public string ProjectGuid { - get { return solutionProject.ProjectGuid; } - } - public string AssemblyName { - get { return nodeProps["AssemblyName"]?.InnerText; } - } - public string OutputType { - get { return nodeProps["OutputType"]?.InnerText; } - } - public string RootNamespace { - get { return nodeProps["RootNamespace"]?.InnerText; } - } - public bool AllowUnsafeBlocks { - get {return nodeProps["AllowUnsafeBlocks"] == null ? false : - bool.Parse (nodeProps["AllowUnsafeBlocks"]?.InnerText); } - } - public bool NoStdLib { - get { return nodeProps["NoStdLib"] == null ? false : - bool.Parse (nodeProps["NoStdLib"]?.InnerText); } - } - public bool TreatWarningsAsErrors { - get { return nodeProps["TreatWarningsAsErrors"] == null ? false: - bool.Parse (nodeProps["TreatWarningsAsErrors"]?.InnerText); } - } - public bool SignAssembly { - get { return bool.Parse (nodeProps["SignAssembly"]?.InnerText); } - } - public string TargetFrameworkVersion { - get { return nodeProps["TargetFrameworkVersion"]?.InnerText; } - } - public string Description { - get { return nodeProps["Description"]?.InnerText; } - } - public string OutputPath { - get { return nodeProps["OutputPath"]?.InnerText; } - } - public string IntermediateOutputPath { - get { return nodeProps["IntermediateOutputPath"]?.InnerText; } - } - public string StartupObject { - get { return nodeProps["StartupObject"]?.InnerText; } - } - public bool DebugSymbols { - get { return nodeProps["DebugSymbols"] == null ? false : bool.Parse( nodeProps["DebugSymbols"]?.InnerText); } - } - public int WarningLevel { - get { return nodeProps["WarningLevel"] == null ? 0 : int.Parse(nodeProps["WarningLevel"]?.InnerText); } - } - - #endregion - - - public void AddNewFile () { - Window.Show(CrowIDE.MainIFace, "#Crow.Coding.ui.NewFile.crow",true).DataSource = this; - } - - public void Load () { - - xmlDoc = new XmlDocument(); - using (Stream ins = new FileStream (this.Path, FileMode.Open)) { - xmlDoc.Load (new XmlTextReader(ins) { Namespaces = false }); - } - - nodeProject = xmlDoc.SelectSingleNode("Project"); - XmlNodeList nodesProps = xmlDoc.SelectNodes ("/Project/PropertyGroup"); - - foreach (XmlNode n in nodesProps) { - if (n.Attributes ["Condition"] == null) - nodeProps = n; - } - nodesItems = xmlDoc.SelectNodes ("/Project/ItemGroup"); - - if (ProjectGuid != solutionProject.ProjectGuid) - throw new Exception ("Project GUID not matching with solution"); - - buildTreeNodes (); - - IsLoaded = true; - } - - public void Save () { - - } - - void setAsStartupProject () { - solution.StartupProject = this; - } - static Regex regexDirTokens = new Regex(@"\$\(([^\)]*)\)|([^\$]*)"); - - string getDirectoryWithTokens (string dir){ - Match m = regexDirTokens.Match (dir); - string tmp = ""; - while (m.Success) - { - if (m.Value == @"$(SolutionDir)") - tmp = System.IO.Path.Combine (tmp, solution.SolutionFolder); - else if (m.Value == @"$(Configuration)") - tmp = System.IO.Path.Combine (tmp, "Debug"); - else - tmp = System.IO.Path.Combine (tmp, m.Value); - - if (tmp.EndsWith (@"\")||tmp.EndsWith (@"/")) - tmp = tmp.Remove (tmp.Length - 1); - - m = m.NextMatch(); - } - return tmp; - } - public string Compile () { - if (ParentProject != null) - ParentProject.Compile (); - - CSharpCodeProvider cp = new CSharpCodeProvider(); - CompilerParameters parameters = new CompilerParameters(); - - foreach (ProjectReference pr in flattenNodes.OfType()) { - Project p = solution.Projects.FirstOrDefault (pp => pp.ProjectGuid == pr.ProjectGUID); - if (p == null) - throw new Exception ("referenced project not found"); - parameters.ReferencedAssemblies.Add (p.Compile ()); - } - - string outputDir = getDirectoryWithTokens(this.OutputPath); - string objDir = getDirectoryWithTokens (this.IntermediateOutputPath); - - Directory.CreateDirectory (outputDir); - Directory.CreateDirectory (objDir); - - parameters.OutputAssembly = System.IO.Path.Combine (outputDir, this.AssemblyName); - - // True - exe file generation, false - dll file generation - if (this.OutputType == "Library") { - parameters.GenerateExecutable = false; - parameters.CompilerOptions += " /target:library"; - parameters.OutputAssembly += ".dll"; - } else { - parameters.GenerateExecutable = true; - parameters.CompilerOptions += " /target:exe"; - parameters.OutputAssembly += ".exe"; - parameters.MainClass = this.StartupObject; - } - - parameters.GenerateInMemory = false; - parameters.IncludeDebugInformation = this.DebugSymbols; - parameters.TreatWarningsAsErrors = this.TreatWarningsAsErrors; - parameters.WarningLevel = this.WarningLevel; - parameters.CompilerOptions += " /noconfig"; - if (this.AllowUnsafeBlocks) - parameters.CompilerOptions += " /unsafe"; - parameters.CompilerOptions += " /delaysign+"; - parameters.CompilerOptions += " /debug:full /debug+"; - parameters.CompilerOptions += " /optimize-"; - parameters.CompilerOptions += " /define:\"DEBUG;TRACE\""; - parameters.CompilerOptions += " /nostdlib"; - - - - foreach (ProjectItem pi in flattenNodes.Where (p=>p.Type == ItemType.Reference)) { - - if (string.IsNullOrEmpty (pi.HintPath)) { - parameters.CompilerOptions += " /reference:/usr/lib/mono/4.5/" + pi.Path + ".dll"; - continue; - } - parameters.ReferencedAssemblies.Add (pi.Path); - string fullHintPath = System.IO.Path.GetFullPath(System.IO.Path.Combine (RootDir, pi.HintPath.Replace('\\','/'))); - if (File.Exists (fullHintPath)) { - string outPath = System.IO.Path.Combine (outputDir, System.IO.Path.GetFileName (fullHintPath)); - if (!File.Exists(outPath)) - File.Copy (fullHintPath, outPath); - } - } - parameters.CompilerOptions += " /reference:/usr/lib/mono/4.5/System.Core.dll"; - parameters.CompilerOptions += " /reference:/usr/lib/mono/4.5/mscorlib.dll"; - //parameters.ReferencedAssemblies.Add ("System.Core"); - //parameters.ReferencedAssemblies.Add ("mscorlib.dll"); - - - IEnumerable pfs = flattenNodes.OfType (); - - foreach (ProjectFile pi in pfs.Where (p => p.Type == ItemType.EmbeddedResource)) { - - string absPath = pi.AbsolutePath; - string logicName = pi.LogicalName; - if (string.IsNullOrEmpty (logicName)) - parameters.CompilerOptions += string.Format (" /resource:{0},{1}", absPath , this.Name + "." + pi.Path.Replace('/','.')); - else - parameters.CompilerOptions += string.Format (" /resource:{0},{1}", absPath, logicName); - } - foreach (ProjectFile pi in pfs.Where (p => p.Type == ItemType.None)) { - if (pi.CopyToOutputDirectory == CopyToOutputState.Never) - continue; - string source = pi.AbsolutePath; - string target = System.IO.Path.Combine (outputDir, pi.Path); - Directory.CreateDirectory (System.IO.Path.GetDirectoryName (target)); - - if (File.Exists (target)) { - if (pi.CopyToOutputDirectory == CopyToOutputState.PreserveNewest) { - if (DateTime.Compare ( - System.IO.File.GetLastWriteTime (source), - System.IO.File.GetLastWriteTime (target)) < 0) - continue; - } - File.Delete (target); - } - System.Diagnostics.Debug.WriteLine ("copy " + source + " to " + target); - File.Copy (source, target); - } - string[] files = pfs.Where (p => p.Type == ItemType.Compile).Select (p => p.AbsolutePath).ToArray(); - - System.Diagnostics.Debug.WriteLine("---- start compilation of :" + parameters.OutputAssembly); - System.Diagnostics.Debug.WriteLine (parameters.CompilerOptions); - - CompilationResults = cp.CompileAssemblyFromFile(parameters, files); - - solution.UpdateErrorList (); - - return parameters.OutputAssembly; - } - - public bool TryGetProjectFileFromAbsolutePath (string absolutePath, out ProjectFile pi){ - pi = flattenNodes.OfType ().FirstOrDefault - (pp => pp.AbsolutePath == absolutePath); - return pi != null; - } - public bool TryGetProjectFileFromPath (string path, out ProjectFile pi){ - if (path.StartsWith ("#")) - pi = flattenNodes.OfType ().FirstOrDefault - (pp => pp.Type == ItemType.EmbeddedResource && pp.ResourceID == path.Substring (1)); - else - pi = flattenNodes.OfType ().FirstOrDefault (pp => pp.Path == path); - - if (pi != null) - return true; - - foreach (ProjectReference pr in flattenNodes.OfType()) { - Project p = solution.Projects.FirstOrDefault (pp => pp.ProjectGuid == pr.ProjectGUID); - if (p == null) - throw new Exception ("referenced project not found"); - if (p.TryGetProjectFileFromPath (path, out pi)) - return true; - } - //TODO: search referenced assemblies - return false; - } - - public void GetDefaultTemplates () { - IEnumerable tmpFiles = - flattenNodes.OfType ().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 (Project p in ReferencedProjects) - 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 List ReferencedProjects { - get { - List tmp = new List (); - foreach (ProjectReference pr in flattenNodes.OfType()) { - Project p = solution.Projects.FirstOrDefault (pp => pp.ProjectGuid == pr.ProjectGUID); - if (p != null) - tmp.Add (p); - } - return tmp; - } - } - - public void GetStyling () { - try { - foreach (ProjectFile pi in flattenNodes.OfType ().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); - } - } - } catch (Exception ex) { - Console.WriteLine (ex.ToString ()); - } - foreach (ProjectReference pr in flattenNodes.OfType()) { - 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 - } - } +namespace Crow.Coding { + public class Project : IValueChange { + #region IValueChange implementation + public event EventHandler ValueChanged; + public virtual void NotifyValueChanged (string MemberName, object _value) { + ValueChanged.Raise (this, new ValueChangeEventArgs (MemberName, _value)); + } + #endregion + + bool isLoaded = false; + bool isExpanded; + XmlDocument xmlDoc; + XmlNode nodeProject; + XmlNode nodeProps; + XmlNodeList nodesItems; + SolutionProject solutionProject; + Crow.Command cmdSave, cmdOpen, cmdCompile, cmdSetAsStartProj, cmdNewFile; + + #region CTOR + public Project (Solution sol, SolutionProject sp) { + solutionProject = sp; + + solution = sol; + + cmdSave = new Crow.Command (new Action (() => Save ())) { Caption = "Save", Icon = new SvgPicture ("#icons.save.svg"), CanExecute = true }; + cmdOpen = new Crow.Command (new Action (() => Load ())) { Caption = "Open", Icon = new SvgPicture ("#icons.open.svg"), CanExecute = false }; + cmdCompile = new Crow.Command (new Action (() => Compile ())) { + Caption = "Compile", + Icon = "#icons.compile.svg" + }; + cmdSetAsStartProj = new Crow.Command (new Action (() => setAsStartupProject ())) { + Caption = "Set as Startup Project" + }; + cmdNewFile = new Crow.Command (new Action (() => AddNewFile ())) { + Caption = "Add New File", + Icon = new SvgPicture ("#icons.blank-file.svg"), + CanExecute = true + }; + + Commands = new List (new Crow.Command[] { cmdOpen, cmdSave, cmdSetAsStartProj, cmdCompile, cmdNewFile }); + + Load (); + } + #endregion + + public Solution solution; + public List Commands; + public CompilerResults CompilationResults; + public List dependantProjects = new List (); + public Project ParentProject = null; + List rootItems; + List flattenNodes; + + public string Name { + get { return solutionProject.ProjectName; } + } + public bool IsLoaded { + get { return isLoaded; } + set { + if (isLoaded == value) + return; + isLoaded = value; + NotifyValueChanged ("IsLoaded", isLoaded); + } + } + public bool IsExpanded { + get { return isExpanded; } + set { + if (value == isExpanded) + return; + isExpanded = value; + NotifyValueChanged ("IsExpanded", isExpanded); + } + } + public bool IsStartupProject { + get { return solution.StartupProject == this; } + } + public string Path { + get { return System.IO.Path.Combine (solution.SolutionFolder, solutionProject.RelativePath.Replace ('\\', '/')); } + } + public string RootDir { + get { return System.IO.Path.GetDirectoryName (Path); } + } + + + + public List RootItems { + get { return rootItems; } + } + + void buildTreeNodes () { + ProjectNode root = new ProjectNode (this, ItemType.VirtualGroup, RootNamespace); + List items = new List (); + foreach (XmlNode i in nodesItems) { + foreach (XmlNode f in i.ChildNodes) { + items.Add (new ProjectItem (this, f)); + } + } + + flattenNodes = new List (); + + ProjectNode refs = new ProjectNode (this, ItemType.ReferenceGroup, "References"); + root.AddChild (refs); + + foreach (ProjectItem pn in items) { + switch (pn.Type) { + case ItemType.Reference: + refs.AddChild (pn); + flattenNodes.Add (pn); + break; + case ItemType.ProjectReference: + ProjectReference pr = new ProjectReference (pn); + refs.AddChild (pr); + flattenNodes.Add (pr); + break; + case ItemType.Compile: + case ItemType.None: + case ItemType.EmbeddedResource: + ProjectNode curNode = root; + string[] folds = pn.Path.Split ('/'); + for (int i = 0; i < folds.Length - 1; i++) { + ProjectNode nextNode = curNode.ChildNodes.FirstOrDefault (n => n.DisplayName == folds[i] && n.Type == ItemType.VirtualGroup); + if (nextNode == null) { + nextNode = new ProjectNode (this, ItemType.VirtualGroup, folds[i]); + curNode.AddChild (nextNode); + } + curNode = nextNode; + } + ProjectNode f = null; + switch (pn.Extension) { + /*case ".cs": + f = new CSProjectFile (pn); + break;*/ + case ".crow": + case ".template": + case ".goml": + case ".itemp": + case ".imtl": + f = new ImlProjectItem (pn); + break; + case ".style": + f = new StyleProjectItem (pn); + break; + default: + f = new ProjectFile (pn); + break; + } + curNode.AddChild (f); + flattenNodes.Add (f); + break; + } + } + root.SortChilds (); + + rootItems = root.ChildNodes; + } + + #region Project properties + public string ToolsVersion { + get { return nodeProject?.Attributes["ToolsVersion"]?.Value; } + } + public string DefaultTargets { + get { return nodeProject?.Attributes["DefaultTargets"]?.Value; } + } + public string ProjectGuid { + get { return solutionProject.ProjectGuid; } + } + public string AssemblyName { + get { return nodeProps["AssemblyName"]?.InnerText; } + } + public string OutputType { + get { return nodeProps["OutputType"]?.InnerText; } + } + public string RootNamespace { + get { return nodeProps["RootNamespace"]?.InnerText; } + } + public bool AllowUnsafeBlocks { + get { + return nodeProps["AllowUnsafeBlocks"] == null ? false : + bool.Parse (nodeProps["AllowUnsafeBlocks"]?.InnerText); + } + } + public bool NoStdLib { + get { + return nodeProps["NoStdLib"] == null ? false : + bool.Parse (nodeProps["NoStdLib"]?.InnerText); + } + } + public bool TreatWarningsAsErrors { + get { + return nodeProps["TreatWarningsAsErrors"] == null ? false : + bool.Parse (nodeProps["TreatWarningsAsErrors"]?.InnerText); + } + } + public bool SignAssembly { + get { return bool.Parse (nodeProps["SignAssembly"]?.InnerText); } + } + public string TargetFrameworkVersion { + get { return nodeProps["TargetFrameworkVersion"]?.InnerText; } + } + public string Description { + get { return nodeProps["Description"]?.InnerText; } + } + public string OutputPath { + get { return nodeProps["OutputPath"]?.InnerText; } + } + public string IntermediateOutputPath { + get { return nodeProps["IntermediateOutputPath"]?.InnerText; } + } + public string StartupObject { + get { return nodeProps["StartupObject"]?.InnerText; } + } + public bool DebugSymbols { + get { return nodeProps["DebugSymbols"] == null ? false : bool.Parse (nodeProps["DebugSymbols"]?.InnerText); } + } + public int WarningLevel { + get { return nodeProps["WarningLevel"] == null ? 0 : int.Parse (nodeProps["WarningLevel"]?.InnerText); } + } + + #endregion + + + public void AddNewFile () { + Window.Show (CrowIDE.MainIFace, "#Crow.Coding.ui.NewFile.crow", true).DataSource = this; + } + + public void Load () { + + xmlDoc = new XmlDocument (); + using (Stream ins = new FileStream (this.Path, FileMode.Open)) { + xmlDoc.Load (new XmlTextReader (ins) { Namespaces = false }); + } + + nodeProject = xmlDoc.SelectSingleNode ("Project"); + XmlNodeList nodesProps = xmlDoc.SelectNodes ("/Project/PropertyGroup"); + + foreach (XmlNode n in nodesProps) { + if (n.Attributes["Condition"] == null) + nodeProps = n; + } + nodesItems = xmlDoc.SelectNodes ("/Project/ItemGroup"); + + if (ProjectGuid != solutionProject.ProjectGuid) + throw new Exception ("Project GUID not matching with solution"); + + buildTreeNodes (); + + IsLoaded = true; + } + + public void Save () { + + } + + void setAsStartupProject () { + solution.StartupProject = this; + } + static Regex regexDirTokens = new Regex (@"\$\(([^\)]*)\)|([^\$]*)"); + + string getDirectoryWithTokens (string dir) { + Match m = regexDirTokens.Match (dir); + string tmp = ""; + while (m.Success) { + if (m.Value == @"$(SolutionDir)") + tmp = System.IO.Path.Combine (tmp, solution.SolutionFolder); + else if (m.Value == @"$(Configuration)") + tmp = System.IO.Path.Combine (tmp, "Debug"); + else + tmp = System.IO.Path.Combine (tmp, m.Value); + + if (tmp.EndsWith (@"\") || tmp.EndsWith (@"/")) + tmp = tmp.Remove (tmp.Length - 1); + + m = m.NextMatch (); + } + return tmp; + } + public string Compile () { + if (ParentProject != null) + ParentProject.Compile (); + + CSharpCodeProvider cp = new CSharpCodeProvider (); + CompilerParameters parameters = new CompilerParameters (); + + foreach (ProjectReference pr in flattenNodes.OfType ()) { + Project p = solution.Projects.FirstOrDefault (pp => pp.ProjectGuid == pr.ProjectGUID); + if (p == null) + throw new Exception ("referenced project not found"); + parameters.ReferencedAssemblies.Add (p.Compile ()); + } + + string outputDir = getDirectoryWithTokens (this.OutputPath); + string objDir = getDirectoryWithTokens (this.IntermediateOutputPath); + + Directory.CreateDirectory (outputDir); + Directory.CreateDirectory (objDir); + + parameters.OutputAssembly = System.IO.Path.Combine (outputDir, this.AssemblyName); + + // True - exe file generation, false - dll file generation + if (this.OutputType == "Library") { + parameters.GenerateExecutable = false; + parameters.CompilerOptions += " /target:library"; + parameters.OutputAssembly += ".dll"; + } else { + parameters.GenerateExecutable = true; + parameters.CompilerOptions += " /target:exe"; + parameters.OutputAssembly += ".exe"; + parameters.MainClass = this.StartupObject; + } + + parameters.GenerateInMemory = false; + parameters.IncludeDebugInformation = this.DebugSymbols; + parameters.TreatWarningsAsErrors = this.TreatWarningsAsErrors; + parameters.WarningLevel = this.WarningLevel; + parameters.CompilerOptions += " /noconfig"; + if (this.AllowUnsafeBlocks) + parameters.CompilerOptions += " /unsafe"; + parameters.CompilerOptions += " /delaysign+"; + parameters.CompilerOptions += " /debug:full /debug+"; + parameters.CompilerOptions += " /optimize-"; + parameters.CompilerOptions += " /define:\"DEBUG;TRACE\""; + parameters.CompilerOptions += " /nostdlib"; + + + + foreach (ProjectItem pi in flattenNodes.Where (p => p.Type == ItemType.Reference)) { + + if (string.IsNullOrEmpty (pi.HintPath)) { + parameters.CompilerOptions += " /reference:/usr/lib/mono/4.5/" + pi.Path + ".dll"; + continue; + } + parameters.ReferencedAssemblies.Add (pi.Path); + string fullHintPath = System.IO.Path.GetFullPath (System.IO.Path.Combine (RootDir, pi.HintPath.Replace ('\\', '/'))); + if (File.Exists (fullHintPath)) { + string outPath = System.IO.Path.Combine (outputDir, System.IO.Path.GetFileName (fullHintPath)); + if (!File.Exists (outPath)) + File.Copy (fullHintPath, outPath); + } + } + parameters.CompilerOptions += " /reference:/usr/lib/mono/4.5/System.Core.dll"; + parameters.CompilerOptions += " /reference:/usr/lib/mono/4.5/mscorlib.dll"; + //parameters.ReferencedAssemblies.Add ("System.Core"); + //parameters.ReferencedAssemblies.Add ("mscorlib.dll"); + + + IEnumerable pfs = flattenNodes.OfType (); + + foreach (ProjectFile pi in pfs.Where (p => p.Type == ItemType.EmbeddedResource)) { + + string absPath = pi.AbsolutePath; + string logicName = pi.LogicalName; + if (string.IsNullOrEmpty (logicName)) + parameters.CompilerOptions += string.Format (" /resource:{0},{1}", absPath, this.Name + "." + pi.Path.Replace ('/', '.')); + else + parameters.CompilerOptions += string.Format (" /resource:{0},{1}", absPath, logicName); + } + foreach (ProjectFile pi in pfs.Where (p => p.Type == ItemType.None)) { + if (pi.CopyToOutputDirectory == CopyToOutputState.Never) + continue; + string source = pi.AbsolutePath; + string target = System.IO.Path.Combine (outputDir, pi.Path); + Directory.CreateDirectory (System.IO.Path.GetDirectoryName (target)); + + if (File.Exists (target)) { + if (pi.CopyToOutputDirectory == CopyToOutputState.PreserveNewest) { + if (DateTime.Compare ( + System.IO.File.GetLastWriteTime (source), + System.IO.File.GetLastWriteTime (target)) < 0) + continue; + } + File.Delete (target); + } + System.Diagnostics.Debug.WriteLine ("copy " + source + " to " + target); + File.Copy (source, target); + } + string[] files = pfs.Where (p => p.Type == ItemType.Compile).Select (p => p.AbsolutePath).ToArray (); + + System.Diagnostics.Debug.WriteLine ("---- start compilation of :" + parameters.OutputAssembly); + System.Diagnostics.Debug.WriteLine (parameters.CompilerOptions); + + CompilationResults = cp.CompileAssemblyFromFile (parameters, files); + + solution.UpdateErrorList (); + + return parameters.OutputAssembly; + } + + public bool TryGetProjectFileFromAbsolutePath (string absolutePath, out ProjectFile pi) { + pi = flattenNodes.OfType ().FirstOrDefault + (pp => pp.AbsolutePath == absolutePath); + return pi != null; + } + public bool TryGetProjectFileFromPath (string path, out ProjectFile pi) { + if (path.StartsWith ("#")) + pi = flattenNodes.OfType ().FirstOrDefault + (pp => pp.Type == ItemType.EmbeddedResource && pp.ResourceID == path.Substring (1)); + else + pi = flattenNodes.OfType ().FirstOrDefault (pp => pp.Path == path); + + if (pi != null) + return true; + + foreach (ProjectReference pr in flattenNodes.OfType ()) { + Project p = solution.Projects.FirstOrDefault (pp => pp.ProjectGuid == pr.ProjectGUID); + if (p == null) + throw new Exception ("referenced project not found"); + if (p.TryGetProjectFileFromPath (path, out pi)) + return true; + } + //TODO: search referenced assemblies + return false; + } + + public void GetDefaultTemplates () { + IEnumerable tmpFiles = + flattenNodes.OfType ().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 (Project p in ReferencedProjects) + 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 List ReferencedProjects { + get { + List tmp = new List (); + foreach (ProjectReference pr in flattenNodes.OfType ()) { + Project p = solution.Projects.FirstOrDefault (pp => pp.ProjectGuid == pr.ProjectGUID); + if (p != null) + tmp.Add (p); + } + return tmp; + } + } + + public void GetStyling () { + try { + foreach (ProjectFile pi in flattenNodes.OfType ().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); + } + } + } catch (Exception ex) { + Console.WriteLine (ex.ToString ()); + } + foreach (ProjectReference pr in flattenNodes.OfType ()) { + 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 + } + } } diff --git a/CrowIDE/src/ProjectTree/CSProjectFile.cs b/CrowIDE/src/ProjectTree/CSProjectFile.cs new file mode 100644 index 00000000..586e2261 --- /dev/null +++ b/CrowIDE/src/ProjectTree/CSProjectFile.cs @@ -0,0 +1,72 @@ +// +// ProjectNodes.cs +// +// Author: +// Jean-Philippe Bruyère +// +// 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 Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Crow.Coding +{ + public class CSProjectFile : ProjectFile + { + CSharpSyntaxTree tree; + + + #region CTOR + public CSProjectFile (ProjectItem pi) : base (pi){ + } + #endregion + + public override void UpdateSource(object sender, string newSrc) + { + base.UpdateSource(sender, newSrc); + + tree = (CSharpSyntaxTree)CSharpSyntaxTree.ParseText (Source, CSharpParseOptions.Default); + } + + public override void Open () { + base.Open (); + + tree = (CSharpSyntaxTree)CSharpSyntaxTree.ParseText (Source, CSharpParseOptions.Default); + + CompilationUnitSyntax root = (CompilationUnitSyntax)tree.GetRoot (); + MemberDeclarationSyntax firstMember = root.Members [0]; + + Console.WriteLine ( firstMember.GetType().FullName); + + SyntaxToken tok = root.GetFirstToken(); + + while (tok.Value != null) { + Console.Write (tok.Text); + tok = tok.GetNextToken (true,true); + } + Console.Out.Flush (); + } + + + } +} + diff --git a/CrowIDE/src/ProjectTree/ProjectFile.cs b/CrowIDE/src/ProjectTree/ProjectFile.cs index 611f1d8b..8d803faa 100644 --- a/CrowIDE/src/ProjectTree/ProjectFile.cs +++ b/CrowIDE/src/ProjectTree/ProjectFile.cs @@ -25,15 +25,13 @@ // THE SOFTWARE. using System; using System.Collections.Generic; -using System.Linq; -using System.Xml; using System.IO; -using Crow; +using System.Linq; using System.Threading; +using System.Xml; -namespace Crow.Coding -{ - public class ProjectFile : ProjectItem { +namespace Crow.Coding { + public class ProjectFile : ProjectItem { bool isOpened = false; DateTime accessTime; string source; @@ -222,7 +220,7 @@ namespace Crow.Coding } } - public void Open () { + public virtual void Open () { accessTime = System.IO.File.GetLastWriteTime (AbsolutePath); using (StreamReader sr = new StreamReader (AbsolutePath)) { source = sr.ReadToEnd (); diff --git a/CrowIDE/ui/DockWindows/GTreeExpITemp.crow b/CrowIDE/ui/DockWindows/GTreeExpITemp.crow index 614e8e7a..ed9e7d98 100644 --- a/CrowIDE/ui/DockWindows/GTreeExpITemp.crow +++ b/CrowIDE/ui/DockWindows/GTreeExpITemp.crow @@ -1,8 +1,8 @@  - +