diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2021-09-18 09:22:04 +0000 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2021-09-18 09:22:04 +0000 |
| commit | f73ce5a6db8949227834d9d65b195bbb9e8acb32 (patch) | |
| tree | 759eac7b86ca8cf03a1cee9796dcd17079bdd02c | |
| parent | 8b343e10f1a65b07988e15ea76596b16a03adadc (diff) | |
save commit, BubbleEvents, iface.search type and ext meth for loadCtx wise searches, IncludedEvents as list, removed discarded events
39 files changed, 527 insertions, 263 deletions
diff --git a/Crow/Default.style b/Crow/Default.style index c2b17b4b..181ed47b 100644 --- a/Crow/Default.style +++ b/Crow/Default.style @@ -100,8 +100,9 @@ Wrapper { } Button { Template = "#Crow.Button.template"; + //Focusable = "true"; Caption = "Button"; - MinimumSize = "50,22"; + MinimumSize = "60,22"; Height = "Fit"; Width = "Fit"; } @@ -163,6 +164,7 @@ ListItem { //Selected = "{Background=${ControlHighlight}}"; //Unselected = "{Background=Transparent}"; //Margin="1"; + Focusable = "true"; } MessageBox { Background = "0.1,0.1,0.2,0.85"; @@ -362,13 +364,13 @@ TableHeaderLabel { Button, CheckBox, RadioButton, ComboBox, Expandable, MessageBox, Popper, Slider, Spinner, TextBox, NumericControl { - //Focusable = "true"; + Focusable = "true"; Foreground="${ControlForeground}"; Height = "Fit"; Background = "${ControlBackground}"; CornerRadius = "${ControlCornerRadius}"; Margin="0"; - BubbleMouseEvent="MouseWheel|Keyboard"; + BubbleEvents="MouseWheel|Keyboard"; } TemplatedControl, GenericStack { CacheEnabled="true"; diff --git a/Crow/Templates/Button.template b/Crow/Templates/Button.template index 9ad621d9..6627021e 100644 --- a/Crow/Templates/Button.template +++ b/Crow/Templates/Button.template @@ -1,4 +1,4 @@ <?xml version="1.0"?> -<Border Style="ButtonBorder" Background="{./Background}" Name="Content" CornerRadius="{../CornerRadius}" > +<Border Style="ButtonBorder" Background="{./Background}" Name="Content" CornerRadius="{../CornerRadius}" Width="Stretched" Height="Stretched" > <Label Font="{./Font}" Name="caption" Margin="${ButtonCaptionMargin}" Foreground="{./Foreground}" Text="{./Caption}"/> </Border> diff --git a/Crow/Templates/CheckBox2.template b/Crow/Templates/CheckBox2.template index 0fa0ffef..68afd0bf 100644 --- a/Crow/Templates/CheckBox2.template +++ b/Crow/Templates/CheckBox2.template @@ -1,7 +1,5 @@ -<Border Foreground="Transparent" MouseEnter="{Foreground=Grey}" MouseLeave="{Foreground=Transparent}"> - <Label Font="{./Font}" Text="{./Caption}" - Margin="1" - Background="{./Background}" - Foreground="{./Foreground}" - TextAlignment="Center"/> -</Border>
\ No newline at end of file +<Label Font="{./Font}" Text="{./Caption}" CornerRadius="{./CornerRadius}" Width="Stretched" + Margin="3" + Background="{./Background}" + Foreground="{./Foreground}" + TextAlignment="Center"/>
\ No newline at end of file diff --git a/Crow/Templates/ContextMenu.template b/Crow/Templates/ContextMenu.template index 2d41ffbf..54df383c 100644 --- a/Crow/Templates/ContextMenu.template +++ b/Crow/Templates/ContextMenu.template @@ -3,8 +3,8 @@ Orientation="Vertical" IsOpened ="true" IsVisible="{/IsOpened}" ItemTemplate="#Crow.MenuItem.itmp"> - <Template> - <GenericStack Orientation="{./Orientation}" Name="ItemsContainer" Margin="0" Background="${MenuBackground}"/> + <Template> + <GenericStack Orientation="{./Orientation}" Name="ItemsContainer" Margin="0" Background="${MenuBackground}"/> </Template> </MenuItem> diff --git a/Crow/Templates/FileDialog.template b/Crow/Templates/FileDialog.template index a349905a..71ed5c2b 100644 --- a/Crow/Templates/FileDialog.template +++ b/Crow/Templates/FileDialog.template @@ -33,7 +33,7 @@ Name="ItemsContainer" Margin="0" Spacing="1"/> </Scroller> <ScrollBar Name="scrollbar1" Orientation="Vertical" - Value="{²../scroller1.ScrollY}" Maximum="{../scroller1.MaxScrollY}" + Value="{²../scroller1.ScrollY}" Maximum="{../scroller1.MaxScrollY}" CursorRatio="{../scroller1.ChildHeightRatio}" LargeIncrement="{../scroller1.PageHeight}" SmallIncrement="30" Width="14" /> @@ -51,8 +51,8 @@ <CheckBox Style="CheckBoxAlt" Name="cbShowHidden" Caption="Show Hidden" IsChecked="{²./ShowHidden}"/> </HorizontalStack> <HorizontalStack Fit="true" HorizontalAlignment="Right" Margin="3" Spacing="3"> - <Button Caption="Ok" MouseClick="./onFileSelect"/> - <Button Caption="Cancel" MouseClick="./onCancel"/> + <Button Caption="Ok" Command="{./CMDOk}"/> + <Button Caption="Cancel" Command="{./CMDCancel}"/> </HorizontalStack> </VerticalStack> </Container> diff --git a/Crow/Templates/MenuButton.template b/Crow/Templates/MenuButton.template index abc3ff2c..8025954b 100644 --- a/Crow/Templates/MenuButton.template +++ b/Crow/Templates/MenuButton.template @@ -1,5 +1,5 @@ <?xml version="1.0"?> -<Button Command="{}" Width="Stretched"> +<Button Command="{}" Width="Stretched" BubbleEvents="All"> <Template> <Label Text="{./Caption}" Width="Stretched" Height="Stretched" Margin="3" MouseEnter="{Background=${ControlHighlight}}" diff --git a/Crow/Templates/MenuItem.itmp b/Crow/Templates/MenuItem.itmp index 7bbf2765..b1d062ab 100644 --- a/Crow/Templates/MenuItem.itmp +++ b/Crow/Templates/MenuItem.itmp @@ -2,6 +2,7 @@ <ItemTemplate DataType="Crow.Command" Path="#Crow.MenuButton.template"/> <ItemTemplate DataType="Crow.CommandGroup" Data="Commands"> <Popper PopDirection="Right" Caption="{Caption}" IsEnabled="{CanExecute}" Width="Stretched" + BubbleEvents="All" MouseEnter="{Background=${ControlHighlight}}" MouseLeave="{Background=Transparent}"> <Template> @@ -9,7 +10,7 @@ <Label Text="{./Caption}" Width="Fit" Height="Stretched"/> <Label Text="..."/> </HorizontalStack> - </Template> + </Template> <VerticalStack Margin="0" Name="ItemsContainer" Fit="true" Background="${MenuBackground}"/> </Popper> </ItemTemplate> diff --git a/Crow/Templates/MenuItem.template b/Crow/Templates/MenuItem.template index 4945b009..4075be94 100644 --- a/Crow/Templates/MenuItem.template +++ b/Crow/Templates/MenuItem.template @@ -1,7 +1,7 @@ <?xml version="1.0"?> <ListItem> <Popper Font="{./Font}" Caption="{./Caption}" Background="{./Background}" PopDirection="{./PopDirection}" - Foreground = "{./Foreground}" BubbleMouseEvent="All" + Foreground = "{./Foreground}" BubbleEvents="All" IsPopped="{²./IsOpened}" PopWidth="{./PopWidth}" PopHeight="{./PopHeight}"> <Template> diff --git a/Crow/Templates/Popper.template b/Crow/Templates/Popper.template index 2a0a0de5..6f3b8440 100644 --- a/Crow/Templates/Popper.template +++ b/Crow/Templates/Popper.template @@ -1,8 +1,8 @@ <?xml version="1.0"?> <Border Style="ControlBorder" Background="{./Background}" CornerRadius="{./CornerRadius}"> <HorizontalStack Spacing="1"> - <Image Style="Icon" - MouseEnter="{Background=White}" MouseLeave="{Background=Transparent}" + <Image Style="Icon" + MouseEnter="{Background=White}" MouseLeave="{Background=Transparent}" Path="#Crow.Icons.expandable.svg" SvgSub="{./IsPopped}"/> <Label Style="ControlCaption" Text="{./Caption}" Foreground="{./Foreground}"/> </HorizontalStack> diff --git a/Crow/src/Colors.cs b/Crow/src/Colors.cs index 323cba2e..d24f5e94 100644 --- a/Crow/src/Colors.cs +++ b/Crow/src/Colors.cs @@ -327,18 +327,18 @@ namespace Crow => value == (UInt32)other;*/ public bool Equals (Color other) - => value == other.value; + => value == other.value; public override int GetHashCode () => value.GetHashCode (); public override string ToString() => EnumsNET.Enums.IsValid<Colors> ((Colors)value) ? EnumsNET.Enums.GetName((Colors)value) : HtmlCode; - + public static Color FromIml (string iml) { Span<double> components = stackalloc double[4]; components[3] = 1;//init alpha to 1 so that it can be ommitted - ReadOnlySpan<char> c = iml.AsSpan (); + ReadOnlySpan<char> c = iml.AsSpan (); int i = 0; int ioc = c.IndexOf (','); @@ -347,7 +347,7 @@ namespace Crow c = c.Slice (ioc + 1); ioc = c.IndexOf (','); } - components[i++] = double.Parse (c); + components[i++] = double.Parse (c); return new Color (components); } diff --git a/Crow/src/DebugUtils/DbgEvent.cs b/Crow/src/DebugUtils/DbgEvent.cs index 1b6144f2..e3144d90 100644 --- a/Crow/src/DebugUtils/DbgEvent.cs +++ b/Crow/src/DebugUtils/DbgEvent.cs @@ -50,7 +50,7 @@ namespace Crow.DebugLogger return null; string [] tmp = str.Trim ().Split (';', StringSplitOptions.None); - DbgEvtType evtType = (DbgEvtType)Enum.Parse (typeof (DbgEvtType), tmp [3]); + DbgEvtType evtType = (DbgEvtType)Enum.Parse (typeof (DbgEvtType), tmp [3]); if (evtType.HasFlag (DbgEvtType.Widget)) { if (evtType.HasFlag (DbgEvtType.Layouting)) @@ -109,13 +109,13 @@ namespace Crow.DebugLogger case DbgEvtType.Update: return Colors.Grey; case DbgEvtType.IFaceLoad: - return Colors.Teal; + return Colors.Teal; default: if (type.HasFlag(DbgEvtType.Mouse)) return Colors.DeepPink; return Colors.White; } } - } + } } }
\ No newline at end of file diff --git a/Crow/src/DebugUtils/DbgEvtType.cs b/Crow/src/DebugUtils/DbgEvtType.cs index 4acd1d27..dff68490 100644 --- a/Crow/src/DebugUtils/DbgEvtType.cs +++ b/Crow/src/DebugUtils/DbgEvtType.cs @@ -9,25 +9,25 @@ namespace Crow [Flags] public enum DbgEvtType : Int32 { None = 0, - IFace = 0x40000000, - Widget = 0x20000000, + IFace = 0x00000100, + Widget = 0x00000200, - Warning = 0x10000000, - Error = 0x08000000, + Warning = 0x00000400, + Error = 0x00000800, - Binding = 0x800000, - Lock = 0x400000, - Layouting = 0x200000, - Clipping = 0x100000, - Drawing = 0x080000, + Binding = 0x00001000, + Lock = 0x00002000, + Layouting = 0x00004000, + Clipping = 0x00008000, + Drawing = 0x00010000, - Focus = 0x040000, - Override = 0x020000, - TemplatedGroup = 0x010000, - Dispose = 0x008000, - Mouse = 0x004000, + Focus = 0x00020000, + Override = 0x00040000, + TemplatedGroup = 0x00080000, + Dispose = 0x00100000, + Mouse = 0x00200000, - Update = IFace | 0x004000, + Update = IFace | 0x00100000, ProcessLayouting = IFace | Update | Lock | Layouting, ClippingRegistration = IFace | Update | Lock | Clipping, ProcessDrawing = IFace | Update | Lock | Drawing, @@ -90,9 +90,14 @@ namespace Crow MouseDown = IFace | Mouse | 0x01, MouseUp = IFace | Mouse | 0x02, MouseMove = IFace | Mouse | 0x03, - GOMouseDown = Widget | Mouse | 0x01, - GOMouseUp = Widget | Mouse | 0x02, - GOMouseMove = Widget | Mouse | 0x03, + MouseEnter = Widget | Mouse | 0x01, + MouseLeave = Widget | Mouse | 0x02, + WidgetMouseMove = Widget | Mouse | 0x03, + WidgetMouseDown = Widget | Mouse | 0x04, + WidgetMouseUp = Widget | Mouse | 0x05, + WidgetMouseWheel = Widget | Mouse | 0x06, + WidgetMouseClick = Widget | Mouse | 0x07, + WidgetMouseDblClick = Widget | Mouse | 0x08, All = 0x7FFFFF00 } diff --git a/Crow/src/DebugUtils/DbgWidgetEvent.cs b/Crow/src/DebugUtils/DbgWidgetEvent.cs index d147ba25..cf61a79b 100644 --- a/Crow/src/DebugUtils/DbgWidgetEvent.cs +++ b/Crow/src/DebugUtils/DbgWidgetEvent.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Threading; namespace Crow.DebugLogger -{ +{ public class DbgWidgetEvent : DbgEvent { public int InstanceIndex; @@ -17,7 +17,7 @@ namespace Crow.DebugLogger InstanceIndex = widgetInstanceIndex; } //public override string Print() => $"{base.Print()}:{InstanceIndex}" - + public override string ToString () => $"{base.ToString ()};{InstanceIndex}"; public override Color Color { @@ -76,6 +76,6 @@ namespace Crow.DebugLogger return Colors.White; } } - } - } + } + } }
\ No newline at end of file diff --git a/Crow/src/DebugUtils/DebugLogger.cs b/Crow/src/DebugUtils/DebugLogger.cs index b84077a6..d549e19d 100644 --- a/Crow/src/DebugUtils/DebugLogger.cs +++ b/Crow/src/DebugUtils/DebugLogger.cs @@ -1,8 +1,7 @@ -using System.Text; -// Copyright (c) 2013-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com> +// Copyright (c) 2013-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com> // // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - +using System.Text; using System; using System.Collections.Generic; using System.Diagnostics; @@ -16,18 +15,21 @@ namespace Crow { public static class DbgLogger { - public static DbgEvtType IncludeEvents = DbgEvtType.All; - public static DbgEvtType DiscardEvents = DbgEvtType.Focus; + /*public static DbgEvtType IncludeEvents = DbgEvtType.All; + public static DbgEvtType DiscardEvents = DbgEvtType.Focus;*/ + + public static List<DbgEvtType> IncludedEvents = new List<DbgEvtType> (); public static bool ConsoleOutput = true; #if DEBUG_LOG - static bool logevt (DbgEvtType evtType) - //=> IncludeEvents != DbgEvtType.None && (evtType & DiscardEvents) == 0 && (evtType & IncludeEvents) == IncludeEvents; - //=> IncludeEvents != DbgEvtType.None && (evtType & DiscardEvents) == 0 && (evtType & IncludeEvents) == IncludeEvents; - => IncludeEvents == DbgEvtType.All || (IncludeEvents != DbgEvtType.None && (evtType & IncludeEvents) != 0); - - + static bool logevt (DbgEvtType evtType) { + foreach (DbgEvtType et in IncludedEvents) { + if ((et & evtType) == et) + return true; + } + return false; + } static object logMutex = new object (); static Stopwatch chrono = Stopwatch.StartNew (); diff --git a/Crow/src/IML/CompilerServices.cs b/Crow/src/IML/CompilerServices.cs index 69c74e42..3888ceaf 100644 --- a/Crow/src/IML/CompilerServices.cs +++ b/Crow/src/IML/CompilerServices.cs @@ -386,29 +386,34 @@ namespace Crow.IML } internal static MethodInfo SearchExtMethod (Type t, string methodName) { - string key = t.Name + "." + methodName; - lock (knownExtMethods) { - if (knownExtMethods.ContainsKey (key)) - return knownExtMethods [key]; + try { + string key = t.Name + "." + methodName; + lock (knownExtMethods) { + if (knownExtMethods.ContainsKey (key)) + return knownExtMethods [key]; - //System.Diagnostics.Console.WriteLine ($"*** search extension method: {t};{methodName} => key={key}"); + //System.Diagnostics.Console.WriteLine ($"*** search extension method: {t};{methodName} => key={key}"); - MethodInfo mi = null; - if (!TryGetExtensionMethods (Assembly.GetEntryAssembly (), t, methodName, out mi)) { - if (!TryGetExtensionMethods (t.Module.Assembly, t, methodName, out mi)) { - foreach (Assembly a in Interface.crowAssemblies) { - if (TryGetExtensionMethods (a, t, methodName, out mi)) - break; + MethodInfo mi = null; + if (!TryGetExtensionMethods (Assembly.GetEntryAssembly (), t, methodName, out mi)) { + if (!TryGetExtensionMethods (t.Module.Assembly, t, methodName, out mi)) { + foreach (Assembly a in Interface.crowAssemblies) { + if (TryGetExtensionMethods (a, t, methodName, out mi)) + break; + } + if (mi == null) + TryGetExtensionMethods (Assembly.GetExecutingAssembly (), t, methodName, out mi);//crow Assembly } - if (mi == null) - TryGetExtensionMethods (Assembly.GetExecutingAssembly (), t, methodName, out mi);//crow Assembly } - } - //add key even if mi is null to prevent searching again and again for propertyless bindings - knownExtMethods.Add (key, mi); - return mi; + //add key even if mi is null to prevent searching again and again for propertyless bindings + knownExtMethods.Add (key, mi); + return mi; + } + } catch (Exception e) {//added this catch for CrowEdit, ext method should be search with appropriate LoadContext. + Debug.WriteLine ($"[CompilerServices.SearchExtMethod]{e}"); } + return null; } public static bool TryGetExtensionMethods (Assembly assembly, Type extendedType, string methodName, out MethodInfo foundMI) diff --git a/Crow/src/IML/Instantiator.cs b/Crow/src/IML/Instantiator.cs index 07ebfd3c..2acace29 100644 --- a/Crow/src/IML/Instantiator.cs +++ b/Crow/src/IML/Instantiator.cs @@ -214,7 +214,7 @@ namespace Crow.IML { while (reader.NodeType != XmlNodeType.Element) reader.Read (); root = reader.Name; - Type t = GetWidgetTypeFromName (root); + Type t = iface.GetWidgetTypeFromName (root); if (t == null) throw new Exception ("IML parsing error: undefined root type (" + root + ")"); return t; @@ -323,7 +323,8 @@ namespace Crow.IML { } if (itemTemplateIds.Count == 0) { //try to load ItemTemplate(s) from ItemTemplate property of TemplatedGroup - if (!string.IsNullOrEmpty (itemTemplatePath)) { + //but don't if it's an binding expression + if (!string.IsNullOrEmpty (itemTemplatePath) && !itemTemplatePath.StartsWith('{')) { //check if it is already loaded in cache as a single itemTemplate instantiator if (iface.ItemTemplates.ContainsKey (itemTemplatePath)) itemTemplateIds.Add (new string [] { "default", itemTemplatePath, "" }); @@ -357,23 +358,30 @@ namespace Crow.IML { } } } + //TODO(09/2021):output an ItemTemplateDecl object instead of an array of string public static IEnumerable<string[]> loadItemTemplatesFromTemplatedGroupProperty (Interface iface, string itemTemplatePath) { using (Stream stream = iface.GetStreamFromPath (itemTemplatePath)) { - //itemtemplate files may have multiple root nodes - XmlReaderSettings itrSettings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment }; - using (XmlReader itr = XmlReader.Create (stream, itrSettings)) { - while (itr.Read ()) { - if (!itr.IsStartElement ()) - continue; - if (itr.NodeType == XmlNodeType.Element) { - if (itr.Name != NT_iTemp) { - //the file contains a single template to use as default - iface.ItemTemplates [itemTemplatePath] = new ItemTemplate (iface, itr); - yield return new string [] { "default", itemTemplatePath, "", "TypeOf" }; - break;//we should be at the end of the file - } - yield return parseItemTemplateTag (iface, itr, itemTemplatePath); + foreach (string[] item in loadItemTemplatesFromTemplatedGroupProperty (iface, stream, itemTemplatePath)) + yield return item; + } + } + public static IEnumerable<string[]> loadItemTemplatesFromTemplatedGroupProperty (Interface iface, Stream stream, string itemTemplatePath = null) { + if (string.IsNullOrEmpty (itemTemplatePath)) + itemTemplatePath = Guid.NewGuid().ToString(); + //itemtemplate files may have multiple root nodes + XmlReaderSettings itrSettings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment }; + using (XmlReader itr = XmlReader.Create (stream, itrSettings)) { + while (itr.Read ()) { + if (!itr.IsStartElement ()) + continue; + if (itr.NodeType == XmlNodeType.Element) { + if (itr.Name != NT_iTemp) { + //the file contains a single template to use as default + iface.ItemTemplates [itemTemplatePath] = new ItemTemplate (iface, itr); + yield return new string [] { "default", itemTemplatePath, "", "TypeOf" }; + break;//we should be at the end of the file } + yield return parseItemTemplateTag (iface, itr, itemTemplatePath); } } } @@ -543,7 +551,7 @@ namespace Crow.IML { ctx.il.Emit (OpCodes.Ldloc_0); ctx.il.Emit (OpCodes.Ldloc_0); - Type t = GetWidgetTypeFromName (reader.Name); + Type t = iface.GetWidgetTypeFromName (reader.Name); if (t == null) throw new Exception (reader.Name + " type not found"); ConstructorInfo ci = t.GetConstructor ( diff --git a/Crow/src/Input/KeyPressEventArgs.cs b/Crow/src/Input/KeyPressEventArgs.cs index cb4e534c..17d1fee2 100644 --- a/Crow/src/Input/KeyPressEventArgs.cs +++ b/Crow/src/Input/KeyPressEventArgs.cs @@ -13,7 +13,7 @@ namespace Crow public class KeyPressEventArgs : CrowEventArgs { char key_char; - + /// <summary> /// Constructs a new instance. /// </summary> diff --git a/Crow/src/Interface.cs b/Crow/src/Interface.cs index ede2927e..46645dee 100644 --- a/Crow/src/Interface.cs +++ b/Crow/src/Interface.cs @@ -360,8 +360,46 @@ namespace Crow } } - internal Dictionary<string, MethodInfo> knownExtMethods = new Dictionary<string, MethodInfo> (); - internal MethodInfo SearchExtMethod (Type t, string methodName) { + protected Dictionary<string, MethodInfo> knownExtMethods; + protected Dictionary<string, Type> knownCrowWidgetTypes; + + /// <summary> + /// search for graphic object type in crow assembly, if not found, + /// search for type independently of namespace in all the loaded assemblies + /// </summary> + /// <remarks> + /// </remarks> + /// <returns>the corresponding type object</returns> + /// <param name="typeName">graphic object type name without its namespace</param> + public virtual Type GetWidgetTypeFromName (string typeName){ + if (knownCrowWidgetTypes.ContainsKey (typeName)) + return knownCrowWidgetTypes [typeName]; + Type t = Type.GetType ("Crow." + typeName); + if (t != null) { + knownCrowWidgetTypes.Add (typeName, t); + return t; + } + + foreach (Type expT in Assembly.GetEntryAssembly ().GetExportedTypes ()) { + if (expT.Name != typeName) + continue; + knownCrowWidgetTypes.Add (typeName, expT); + return expT; + } + + foreach (Assembly a in Interface.crowAssemblies) { + foreach (Type expT in a.GetExportedTypes ()) { + if (expT.Name != typeName) + continue; + knownCrowWidgetTypes.Add (typeName, expT); + return expT; + } + } + return null; + } + + + public virtual MethodInfo SearchExtMethod (Type t, string methodName) { string key = t.Name + "." + methodName; if (knownExtMethods.ContainsKey (key)) return knownExtMethods [key]; @@ -790,6 +828,8 @@ namespace Crow DefaultValuesLoader = new Dictionary<string, LoaderInvoker> (initCapacity); Instantiators = new Dictionary<string, Instantiator> (initCapacity); ItemTemplates = new Dictionary<string, ItemTemplate> (initCapacity); + knownCrowWidgetTypes = new Dictionary<string, Type> (initCapacity); + knownExtMethods = new Dictionary<string, MethodInfo> (initCapacity); } void loadThemeFiles () { if (string.IsNullOrEmpty (Theme)) @@ -1033,6 +1073,9 @@ namespace Crow } _hoverWidget = value; + if (_hoverWidget.ToString() == "HelloWorld.Program.vs2.Border12") + Debugger.Break(); + NotifyValueChanged ("HoverWidget", _hoverWidget); DbgLogger.AddEvent (DbgEvtType.HoverWidget, _hoverWidget); @@ -1840,10 +1883,12 @@ namespace Crow return true; } - if (doubleClickTriggered) - _activeWidget.onMouseDoubleClick (_activeWidget, new MouseButtonEventArgs (MousePosition.X, MousePosition.Y, button, InputAction.Press)); - else - _activeWidget.onMouseClick (_activeWidget, new MouseButtonEventArgs (MousePosition.X, MousePosition.Y, button, InputAction.Press)); + if (_focusedWidget != null &&_focusedWidget.MouseIsIn(MousePosition)) { + if (doubleClickTriggered) + _activeWidget.onMouseDoubleClick (_activeWidget, new MouseButtonEventArgs (MousePosition.X, MousePosition.Y, button, InputAction.Press)); + else + _activeWidget.onMouseClick (_activeWidget, new MouseButtonEventArgs (MousePosition.X, MousePosition.Y, button, InputAction.Press)); + } ActiveWidget = null; // if (!lastActive.MouseIsIn (Mouse.Position)) { @@ -2057,7 +2102,7 @@ namespace Crow else ctxMenuContainer.IsOpened = true; - ctxMenuContainer.BubbleMouseEvent = DeviceEventType.None; + ctxMenuContainer.BubbleEvents = DeviceEventType.None; ctxMenuContainer.LogicalParent = go; ctxMenuContainer.DataSource = go; diff --git a/Crow/src/ItemTemplate.cs b/Crow/src/ItemTemplate.cs index 9fcbd7fb..c263b656 100644 --- a/Crow/src/ItemTemplate.cs +++ b/Crow/src/ItemTemplate.cs @@ -14,7 +14,10 @@ using System.Diagnostics; using System.Linq; using Crow.IML; using System.Collections; - +//TODO(09/2021): itemTemplate are created with datatest and datatype only to be able +//to get their original iml, but itor part takes no advantage of it. +//One advantage could be to set the DataSourceType (which speed bindings by bypassing reflection) +//at the root level of the item template if the dataTest is 'typeOf'... namespace Crow { /// <summary> Test func on data, return yes if there's children </summary> diff --git a/Crow/src/Text/SpanCharReader.cs b/Crow/src/Text/SpanCharReader.cs index 6c6fcde0..5b206575 100644 --- a/Crow/src/Text/SpanCharReader.cs +++ b/Crow/src/Text/SpanCharReader.cs @@ -32,27 +32,27 @@ namespace Crow.Text return true; } public bool TryRead (char c) => EndOfSpan ? false : Read() == c; - + public ReadOnlySpan<char> Read (int length) => buffer.Slice (curPos += length, length); public void Advance (int increment = 1) => curPos += increment; - public bool TryAdvance (int increment = 1) { + public bool TryAdvance (int increment = 1) { curPos += increment; return curPos < buffer.Length; } - + public bool TryReadUntil (ReadOnlySpan<char> str, StringComparison comparison = StringComparison.Ordinal) { int startPos = curPos; while (curPos < buffer.Length - str.Length) { if (buffer[curPos] == str[0] && buffer.Slice(curPos + 1, str.Length - 1).Equals(str.Slice (1), comparison)) return true; - curPos++; + curPos++; } return false; } public bool TryReadUntil (char c) { int startPos = curPos; while (curPos < buffer.Length && buffer[curPos] != c) - curPos++; + curPos++; return curPos < buffer.Length; } public bool TryRead (int length, out ReadOnlySpan<char> str) { @@ -63,7 +63,7 @@ namespace Crow.Text str = default; return false; } - + /// <summary> /// Try read expected string and advance reader position in any case /// </summary> @@ -81,22 +81,68 @@ namespace Crow.Text } public bool TryPeak (ReadOnlySpan<char> expectedString, StringComparison comparison = StringComparison.Ordinal) => (buffer.Length < curPos + expectedString.Length)? false : - buffer.Slice(curPos, expectedString.Length).Equals (expectedString, comparison); - + buffer.Slice(curPos, expectedString.Length).Equals (expectedString, comparison); + + /// <summary> + /// Retrieve a span of that buffer from provided starting position to the current reader position. + /// </summary> + /// <param name="fromPosition"></param> + /// <returns></returns> public ReadOnlySpan<char> Get (int fromPosition) => buffer.Slice (fromPosition, curPos - fromPosition); - public bool EndOfSpan => curPos >= buffer.Length; + /// <summary> + /// Current reader position is further the end of the buffer. + /// </summary> + public bool EndOfSpan => curPos >= buffer.Length; public bool TryPeak (char c) => !EndOfSpan && Peak == c; + /// <summary> + /// Try peak one char, return false if end of span, true otherwise. + /// </summary> + /// <param name="c"></param> + /// <returns></returns> public bool TryPeak (ref char c) { if (EndOfSpan) return false; c = buffer[curPos]; return true; } + /// <summary> + /// test if next char is one of the provided one as parameter + /// </summary> + /// <param name="chars"></param> + /// <returns></returns> public bool IsNextCharIn (params char[] chars) { for (int i = 0; i < chars.Length; i++) if (chars[i] == buffer[curPos]) return true; return false; } + /// <summary> + /// increment reader position just before the next end of line + /// </summary> + public void AdvanceUntilEol () { + while(!EndOfSpan) { + switch (Peak) { + case '\x85': + case '\x2028': + case '\xA': + return; + case '\xD': + int nextPos = curPos + 1; + if (nextPos == buffer.Length || buffer[nextPos] == '\xA' || buffer[nextPos] == '\x85') + return; + break; + } + Advance (); + } + } + /// <summary> + /// Next char or pair of chars is end of line. + /// </summary> + /// <returns></returns> + public bool Eol () { + return Peak == '\x85' || Peak == '\x2028' || Peak == '\xA' || curPos + 1 == buffer.Length || + (Peak == '\xD' && (buffer [curPos + 1] == '\xA' || buffer [curPos + 1] == '\x85')); + + } } } diff --git a/Crow/src/Widgets/Expandable.cs b/Crow/src/Widgets/Expandable.cs index 95e743ea..62b0f1c3 100644 --- a/Crow/src/Widgets/Expandable.cs +++ b/Crow/src/Widgets/Expandable.cs @@ -58,6 +58,7 @@ namespace Crow public void onClickForExpand (object sender, MouseButtonEventArgs e) { IsExpanded = !IsExpanded; + e.Handled = true; } #region Public properties diff --git a/Crow/src/Widgets/FileDialog.cs b/Crow/src/Widgets/FileDialog.cs index bc6b46c0..302818bf 100644 --- a/Crow/src/Widgets/FileDialog.cs +++ b/Crow/src/Widgets/FileDialog.cs @@ -14,9 +14,17 @@ namespace Crow public class FileDialog: Window { #region CTOR - protected FileDialog() : base(){} + protected FileDialog() : base() {} public FileDialog (Interface iface) : base(iface){} #endregion + protected override void loadTemplate(Widget template = null) + { + if (CMDOk == null) { + CMDOk = new ActionCommand (this, "Ok", validate, null, new KeyBinding (Glfw.Key.Enter)); + CMDCancel = new ActionCommand (this, "Cancel", () => IFace.DeleteWidget (this), null, new KeyBinding (Glfw.Key.Escape)); + } + base.loadTemplate(template); + } string searchPattern, curDir, _selectedFile, _selectedDir; bool showHidden, showFiles; @@ -25,6 +33,9 @@ namespace Crow public event EventHandler OkClicked; #endregion + [XmlIgnore]public ActionCommand CMDOk { get; set;} + [XmlIgnore]public ActionCommand CMDCancel { get; set;} + public string SelectedFileFullPath { get { return Path.Combine (SelectedDirectory, SelectedFile); } } @@ -115,20 +126,22 @@ namespace Crow CurrentDirectory = SelectedDirectory; } - void onFileSelect (object sender, MouseButtonEventArgs e){ + void validate () { if (ShowFiles) { if (string.IsNullOrEmpty (SelectedFile)) { CurrentDirectory = SelectedDirectory; return; - } + } } OkClicked.Raise (this, null); IFace.DeleteWidget (this); } - void onCancel(object sender, MouseButtonEventArgs e){ - IFace.DeleteWidget (this); + protected override void Dispose(bool disposing) + { + CMDOk?.Dispose (); + CMDCancel?.Dispose (); + base.Dispose(disposing); } - } } diff --git a/Crow/src/Widgets/MenuItem.cs b/Crow/src/Widgets/MenuItem.cs index e9160095..fd5a4984 100644 --- a/Crow/src/Widgets/MenuItem.cs +++ b/Crow/src/Widgets/MenuItem.cs @@ -140,7 +140,8 @@ namespace Crow { if (IsOpened) IsOpened = false; - base.onMouseLeave (this, e); + if (mouseIsEntered) + base.onMouseLeave (this, e); } public override void onMouseClick (object sender, MouseButtonEventArgs e) { diff --git a/Crow/src/Widgets/TemplatedGroup.cs b/Crow/src/Widgets/TemplatedGroup.cs index 6621c27c..e67625fe 100644 --- a/Crow/src/Widgets/TemplatedGroup.cs +++ b/Crow/src/Widgets/TemplatedGroup.cs @@ -6,6 +6,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; +using System.IO; using System.Linq; using System.Threading; @@ -114,13 +115,33 @@ namespace Crow { ItemTemplates.Clear(); if (string.IsNullOrEmpty (_itemTemplate)) return; - foreach (string[] itempIds in Instantiator.loadItemTemplatesFromTemplatedGroupProperty (IFace, _itemTemplate)) { - ItemTemplate itemp = IFace.GetItemTemplate (itempIds[1]); - ItemTemplates.Add (itempIds[0], itemp); - if (string.IsNullOrEmpty (itempIds[2])) - continue; - itemp.CreateExpandDelegate (this); + if (_itemTemplate.Trim().StartsWith('<')) {//iml fragment in property + using (Stream stream = new MemoryStream (System.Text.Encoding.UTF8.GetBytes (_itemTemplate))) { + foreach (string[] itempIds in Instantiator.loadItemTemplatesFromTemplatedGroupProperty (IFace, stream)) { + ItemTemplate itemp = IFace.GetItemTemplate (itempIds[1]); + ItemTemplates.Add (itempIds[0], itemp); + if (string.IsNullOrEmpty (itempIds[2])) + continue; + itemp.CreateExpandDelegate (this); + } + } + } else { + foreach (string[] itempIds in Instantiator.loadItemTemplatesFromTemplatedGroupProperty (IFace, _itemTemplate)) { + ItemTemplate itemp = IFace.GetItemTemplate (itempIds[1]); + ItemTemplates.Add (itempIds[0], itemp); + if (string.IsNullOrEmpty (itempIds[2])) + continue; + itemp.CreateExpandDelegate (this); + } } + realoadDatas (); + } + void realoadDatas () { + if (data == null) + return; + IEnumerable dataSave = data; + Data = null; + Data = dataSave; } protected override void loadTemplate(Widget template = null) { @@ -234,8 +255,10 @@ namespace Crow { lock (IFace.UpdateMutex) ClearItems (); - if (data == null) + if (data == null) { + NotifyValueChanged ("HasItems", false); return; + } if (data is ICollection c) { if (c.Count == 0) { @@ -504,7 +527,7 @@ namespace Crow { itempKey = dataType.FullName;//fallback to full type name } } - if (ItemTemplates.ContainsKey (itempKey)) + if (!string.IsNullOrEmpty (itempKey) && ItemTemplates.ContainsKey (itempKey)) iTemp = ItemTemplates [itempKey]; else { if (_dataTest == "TypeOf") {//item template selection on full type name diff --git a/Crow/src/Widgets/Widget.cs b/Crow/src/Widgets/Widget.cs index 0b5b4463..1f7c1b08 100644 --- a/Crow/src/Widgets/Widget.cs +++ b/Crow/src/Widgets/Widget.cs @@ -27,7 +27,7 @@ namespace Crow /// <summary> /// The base class for all the graphic tree elements. /// </summary> - public class Widget : ILayoutable, IValueChange, IDisposable + public class Widget : ILayoutable, ICommandHost, IDisposable { internal ReaderWriterLockSlim parentRWLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); #if DEBUG_LOG @@ -140,9 +140,7 @@ namespace Crow } return di; } - public string DesignName { - get { return GetType ().Name + design_id; } - } + public string DesignName => LogName + design_id; #endif #region IDisposable implementation @@ -558,7 +556,7 @@ namespace Crow public virtual string Name { get { #if DEBUG_LOG - return string.IsNullOrEmpty(name) ? this.GetType().Name + GraphicObjects.IndexOf(this).ToString () : name; + return string.IsNullOrEmpty(name) ? this.LogName + GraphicObjects.IndexOf(this).ToString () : name; #else return name; #endif @@ -774,7 +772,7 @@ namespace Crow /// </summary> [DesignCategory ("Behaviour")] [DefaultValue (DeviceEventType.All)] - public virtual DeviceEventType BubbleMouseEvent { + public virtual DeviceEventType BubbleEvents { get => bubbledEvents; set { if (bubbledEvents == value) @@ -1971,7 +1969,6 @@ namespace Crow ctx.Fill (); ctx.Operator = Operator.Over; } - ctx.SetSource (bmp, rb.X, rb.Y); ctx.Paint (); #if VKVG @@ -2060,19 +2057,19 @@ namespace Crow public virtual void onKeyDown(object sender, KeyEventArgs e){ if (KeyDown != null) KeyDown.Invoke (this, e); - else if (!e.Handled && BubbleMouseEvent.HasFlag (DeviceEventType.KeyDown)) + else if (!e.Handled && BubbleEvents.HasFlag (DeviceEventType.KeyDown)) FocusParent?.onKeyDown (sender, e); } public virtual void onKeyUp(object sender, KeyEventArgs e){ if (KeyUp != null) KeyUp.Invoke (this, e); - else if (!e.Handled && BubbleMouseEvent.HasFlag (DeviceEventType.KeyUp)) + else if (!e.Handled && BubbleEvents.HasFlag (DeviceEventType.KeyUp)) FocusParent?.onKeyUp (sender, e); } public virtual void onKeyPress(object sender, KeyPressEventArgs e){ if (KeyPress != null) KeyPress.Invoke (this, e); - else if (!e.Handled && BubbleMouseEvent.HasFlag (DeviceEventType.KeyPress)) + else if (!e.Handled && BubbleEvents.HasFlag (DeviceEventType.KeyPress)) FocusParent?.onKeyPress (sender, e); } #endregion @@ -2123,7 +2120,7 @@ namespace Crow if (MouseMove != null) MouseMove.Invoke (this, e); - else if (!e.Handled && BubbleMouseEvent.HasFlag (DeviceEventType.MouseMove)) + else if (!e.Handled && BubbleEvents.HasFlag (DeviceEventType.MouseMove)) FocusParent?.onMouseMove (sender, e); } /// <summary> @@ -2135,7 +2132,8 @@ namespace Crow /// <param name="sender">Sender of the event</param> /// <param name="e">mouse button pressed event arguments</param> public virtual void onMouseDown(object sender, MouseButtonEventArgs e){ - if (Focusable) { + DbgLogger.AddEvent (DbgEvtType.MouseDown, this); + if (Focusable && !HasFocus) { IFace.FocusedWidget = this; e.Handled = true; } @@ -2145,9 +2143,8 @@ namespace Crow e.Handled = true; } - if (MouseDown != null) - MouseDown?.Invoke (this, e); - else if (!e.Handled && BubbleMouseEvent.HasFlag (DeviceEventType.ButtonDown)) + MouseDown?.Invoke (this, e); + if (!e.Handled && BubbleEvents.HasFlag (DeviceEventType.ButtonDown)) FocusParent?.onMouseDown (sender, e); } /// <summary> @@ -2159,10 +2156,10 @@ namespace Crow /// <param name="sender">Sender of the event</param> /// <param name="e">mouse button release event arguments</param> public virtual void onMouseUp(object sender, MouseButtonEventArgs e){ - + DbgLogger.AddEvent (DbgEvtType.WidgetMouseUp, this); if (MouseUp != null) MouseUp.Invoke (this, e); - else if (!e.Handled && BubbleMouseEvent.HasFlag (DeviceEventType.ButtonUp)) + if (!e.Handled && BubbleEvents.HasFlag (DeviceEventType.ButtonUp)) FocusParent?.onMouseUp (sender, e); } /// <summary> @@ -2171,9 +2168,10 @@ namespace Crow /// <param name="sender">The Sender of the event</param> /// <param name="e">event arguments</param> public virtual void onMouseClick(object sender, MouseButtonEventArgs e){ + DbgLogger.AddEvent (DbgEvtType.WidgetMouseClick, this); if (MouseClick != null) MouseClick.Invoke (this, e); - else if (!e.Handled && BubbleMouseEvent.HasFlag (DeviceEventType.MouseClick)) + if (!e.Handled && BubbleEvents.HasFlag (DeviceEventType.MouseClick)) FocusParent?.onMouseClick (sender, e); } /// <summary> @@ -2183,19 +2181,24 @@ namespace Crow /// <param name="sender">The Sender of the event</param> /// <param name="e">event arguments</param> public virtual void onMouseDoubleClick(object sender, MouseButtonEventArgs e){ + DbgLogger.AddEvent (DbgEvtType.WidgetMouseDblClick, this); if (MouseDoubleClick != null) MouseDoubleClick.Invoke (this, e); - else if (!e.Handled && BubbleMouseEvent.HasFlag (DeviceEventType.MouseClick)) + if (!e.Handled && BubbleEvents.HasFlag (DeviceEventType.MouseClick)) FocusParent?.onMouseDoubleClick (sender, e); } public virtual void onMouseWheel(object sender, MouseWheelEventArgs e){ + DbgLogger.AddEvent (DbgEvtType.WidgetMouseWheel, this); if (MouseWheelChanged != null) MouseWheelChanged.Invoke (this, e); - else if (!e.Handled && BubbleMouseEvent.HasFlag (DeviceEventType.MouseWheel)) + if (!e.Handled && BubbleEvents.HasFlag (DeviceEventType.MouseWheel)) FocusParent?.onMouseWheel (sender, e); } + protected bool mouseIsEntered; public virtual void onMouseEnter(object sender, MouseMoveEventArgs e) { + DbgLogger.AddEvent (DbgEvtType.MouseEnter, this); + mouseIsEntered = true; IFace.MouseCursor = MouseCursor; /*if (IFace.DragAndDropOperation != null) { Widget g = this; @@ -2216,6 +2219,8 @@ namespace Crow } public virtual void onMouseLeave(object sender, MouseMoveEventArgs e) { + DbgLogger.AddEvent (DbgEvtType.MouseLeave, this); + mouseIsEntered = false; MouseLeave.Raise (this, e); } @@ -2312,8 +2317,8 @@ namespace Crow w = w.FocusParent; } this.onMouseLeave (this, e); - IFace.HoverWidget = null; - IFace.OnMouseMove (IFace.MousePosition.X, IFace.MousePosition.Y); + IFace.HoverWidget = FocusParent; + //IFace.OnMouseMove (IFace.MousePosition.X, IFace.MousePosition.Y); } } diff --git a/Crow/src/styling/StyleReader.cs b/Crow/src/styling/StyleReader.cs index 23e3047c..a056283a 100644 --- a/Crow/src/styling/StyleReader.cs +++ b/Crow/src/styling/StyleReader.cs @@ -54,7 +54,7 @@ namespace Crow return (Char)Peek(); } void SkipWhiteSpaceAndLineBreak (){ - while (!EndOfStream){ + while (!EndOfStream){ if (!PeekChar ().IsWhiteSpaceOrNewLine ()) break; if (ReadChar () == '\n') { @@ -102,108 +102,108 @@ namespace Crow }else throw new ParserException (line, column, $"Unexpected char '{PeekChar ()}'", resId); break; - case ',': - ReadChar (); - if (curState != States.classNames || token.Length == 0) - throw new ParserException (line, column, "Unexpected char ','", resId); - targetsClasses.Add (token.ToString()); - token.Clear(); - curState = States.classNames; - break; - case '{': - ReadChar (); - if (curState != States.classNames || token.Length == 0) - throw new ParserException (line, column, "Unexpected char '{'", resId); - targetsClasses.Add (token.ToString()); - token.Clear(); - curState = States.members; - break; - case '}': - ReadChar (); - if (curState != States.members) - throw new ParserException (line, column, "Unexpected char '}'", resId); - curState = States.classNames; - targetsClasses.Clear (); - break; - case '=': - ReadChar (); - if (!(curState == States.members || curState == States.classNames) || token.Length == 0) - throw new ParserException (line, column, "Unexpected char '='", resId); - currentProperty = token.ToString (); - token.Clear (); - curState = States.value; - break; - case '"': - if (curState != States.value) - throw new ParserException (line, column, "Unexpected char '\"'", resId); - ReadChar (); + case ',': + ReadChar (); + if (curState != States.classNames || token.Length == 0) + throw new ParserException (line, column, "Unexpected char ','", resId); + targetsClasses.Add (token.ToString()); + token.Clear(); + curState = States.classNames; + break; + case '{': + ReadChar (); + if (curState != States.classNames || token.Length == 0) + throw new ParserException (line, column, "Unexpected char '{'", resId); + targetsClasses.Add (token.ToString()); + token.Clear(); + curState = States.members; + break; + case '}': + ReadChar (); + if (curState != States.members) + throw new ParserException (line, column, "Unexpected char '}'", resId); + curState = States.classNames; + targetsClasses.Clear (); + break; + case '=': + ReadChar (); + if (!(curState == States.members || curState == States.classNames) || token.Length == 0) + throw new ParserException (line, column, "Unexpected char '='", resId); + currentProperty = token.ToString (); + token.Clear (); + curState = States.value; + break; + case '"': + if (curState != States.value) + throw new ParserException (line, column, "Unexpected char '\"'", resId); + ReadChar (); - while (!EndOfStream) { - char c = ReadChar (); - if (c == '$') { - if (PeekChar () == '{') { - ReadChar (); - //constant replacement - while (!EndOfStream) { - c = ReadChar (); - if (c == '}') - break; - constantId.Append (c); + while (!EndOfStream) { + char c = ReadChar (); + if (c == '$') { + if (PeekChar () == '{') { + ReadChar (); + //constant replacement + while (!EndOfStream) { + c = ReadChar (); + if (c == '}') + break; + constantId.Append (c); + } + if (constantId.Length == 0) + throw new ParserException (line, column, "Empty constant id in styling", resId); + string cst = constantId.ToString (); + constantId.Clear (); + if (!StylingConstants.ContainsKey (cst)) + throw new ParserException (line, column, $"Constant id not found in styling ({cst})", resId); + token.Append (StylingConstants[cst]); + continue; } - if (constantId.Length == 0) - throw new ParserException (line, column, "Empty constant id in styling", resId); - string cst = constantId.ToString (); - constantId.Clear (); - if (!StylingConstants.ContainsKey (cst)) - throw new ParserException (line, column, $"Constant id not found in styling ({cst})", resId); - token.Append (StylingConstants[cst]); - continue; + } else if (c == '\"') { + curState = States.endOfStatement; + break; } - } else if (c == '\"') { - curState = States.endOfStatement; - break; + token.Append (c); } - token.Append (c); - } - break; - case ';': - if (curState != States.endOfStatement) - throw new ParserException (line, column, "Unexpected end of statement", resId); - ReadChar (); - if (targetsClasses.Count == 0) { - //only first style constants kept. - if (!StylingConstants.ContainsKey (currentProperty)) - StylingConstants[currentProperty] = token.ToString (); - curState = States.classNames; - } else { - foreach (string tc in targetsClasses) { - if (!Styling.ContainsKey (tc)) - Styling [tc] = new Style (); - if (!Styling[tc].ContainsKey (currentProperty)) { - Styling[tc][currentProperty] = token.ToString (); -#if DESIGN_MODE - Styling [tc].Locations[currentProperty] = new FileLocation(resId, line, column - token.Length - 1, token.Length); -#endif + break; + case ';': + if (curState != States.endOfStatement) + throw new ParserException (line, column, "Unexpected end of statement", resId); + ReadChar (); + if (targetsClasses.Count == 0) { + //only first style constants kept. + if (!StylingConstants.ContainsKey (currentProperty)) + StylingConstants[currentProperty] = token.ToString (); + curState = States.classNames; + } else { + foreach (string tc in targetsClasses) { + if (!Styling.ContainsKey (tc)) + Styling [tc] = new Style (); + if (!Styling[tc].ContainsKey (currentProperty)) { + Styling[tc][currentProperty] = token.ToString (); + #if DESIGN_MODE + Styling [tc].Locations[currentProperty] = new FileLocation(resId, line, column - token.Length - 1, token.Length); + #endif + } } + curState = States.members; } - curState = States.members; - } - token.Clear (); - currentProperty = null; - break; - default: - if (curState == States.value) - throw new ParserException (line, column, "expecting value enclosed in '\"'", resId); - if (curState == States.endOfStatement) - throw new ParserException (line, column, "expecting end of statement", resId); + token.Clear (); + currentProperty = null; + break; + default: + if (curState == States.value) + throw new ParserException (line, column, "expecting value enclosed in '\"'", resId); + if (curState == States.endOfStatement) + throw new ParserException (line, column, "expecting end of statement", resId); - if (nextCharIsValidCharStartName) { - token.Append (ReadChar ()); - while (nextCharIsValidCharName) + if (nextCharIsValidCharStartName) { token.Append (ReadChar ()); + while (nextCharIsValidCharName) + token.Append (ReadChar ()); + } + break; } - break; - } } } diff --git a/Directory.Build.props b/Directory.Build.props index a0ea5fb5..ba354726 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -15,7 +15,7 @@ <!-- Compile with logging enabled, this will slow down apps, use this only for debugging purpose--> - <CrowDebugLogEnabled>false</CrowDebugLogEnabled> + <CrowDebugLogEnabled>true</CrowDebugLogEnabled> <!-- Collect several statistics on widgets--> <CrowDebugStatsEnabled>false</CrowDebugStatsEnabled> @@ -3,10 +3,10 @@ <a href="http://www.amitmerchant.com/electron-markdownify"> <img src="https://github.com/jpbruyere/Crow/blob/master/Images/crow.png" alt="C.R.O.W." width="140"> </a> - <br> + <br> <br> C# Rapid Open Widgets - <br> + <br> <p align="center"> <a href="https://www.nuget.org/packages/Crow"><img src="https://buildstats.info/nuget/Crow"></a> <a href="https://travis-ci.org/jpbruyere/Crow"> @@ -20,7 +20,7 @@ </a> <a href="https://gitter.im/CSharpRapidOpenWidgets?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"> <img src="https://badges.gitter.im/CSharpRapidOpenWidgets.svg"> - </a> + </a> </p> </h1> diff --git a/Samples/HelloWorld/main.cs b/Samples/HelloWorld/main.cs index e2be248e..dc5e2a13 100644 --- a/Samples/HelloWorld/main.cs +++ b/Samples/HelloWorld/main.cs @@ -5,7 +5,18 @@ using Samples; namespace HelloWorld { class Program : SampleBase { + public CommandGroup CMDTest = new CommandGroup ( + new ActionCommand("Action", ()=> Console.WriteLine ("Action executed")) + ); static void Main (string[] args) { + DbgLogger.IncludedEvents.AddRange ( new DbgEvtType[] { + DbgEvtType.MouseEnter, + DbgEvtType.MouseLeave, + DbgEvtType.WidgetMouseDown, + DbgEvtType.WidgetMouseUp, + DbgEvtType.WidgetMouseClick, + DbgEvtType.HoverWidget + }); using (Interface app = new Program ()) { app.Initialized += (sender, e) => (sender as Interface).Load ("#HelloWorld.helloworld.crow").DataSource = sender; app.Run (); diff --git a/Samples/HelloWorld/ui/helloworld.crow b/Samples/HelloWorld/ui/helloworld.crow index fe05d1e2..a9dad40c 100644 --- a/Samples/HelloWorld/ui/helloworld.crow +++ b/Samples/HelloWorld/ui/helloworld.crow @@ -1,2 +1,40 @@ <?xml version="1.0"?> -<Label Text="Hello World"/>
\ No newline at end of file +<VerticalStack Margin="50" Spacing="20"> + <HorizontalStack Height="Fit"> + <Label Text="Hover:" Width="50" Foreground="Grey"/> + <Label Text="{HoverWidget}" Font="mono, 8"/> + </HorizontalStack> + <HorizontalStack Height="Fit"> + <Label Text="Focus:" Width="50" Foreground="Grey"/> + <Label Text="{FocusedWidget}" Font="mono, 8"/> + </HorizontalStack> + <HorizontalStack Height="Fit"> + <Label Text="Active:" Width="50" Foreground="Grey"/> + <Label Text="{ActiveWidget}" Font="mono, 8"/> + </HorizontalStack> + <Border Height="Fit" Margin="2" Background="Blue" ContextCommands="{CMDTest}" Focusable="true" + MouseEnter="{Background=Red}" + MouseLeave="{Background=Blue}"> + <Label Margin="5" Text="Hello World" /> + </Border> + <Border Height="Fit" Margin="2" Background="Blue" ContextCommands="{CMDTest}" Focusable="true" + MouseEnter="{Background=Red}" + MouseLeave="{Background=Blue}"> + <Label Margin="5" Text="Hello World" /> + </Border> + <Border Height="Fit" Margin="2" Background="Blue" ContextCommands="{CMDTest}" Focusable="true" + MouseEnter="{Background=Red}" + MouseLeave="{Background=Blue}"> + <Label Margin="5" Text="Hello World" /> + </Border> + <Border Height="Fit" Margin="2" Background="Blue" ContextCommands="{CMDTest}" Focusable="true" + MouseEnter="{Background=Red}" + MouseLeave="{Background=Blue}"> + <Label Margin="5" Text="Hello World" /> + </Border> + <Border Height="Fit" Margin="2" Background="Blue" ContextCommands="{CMDTest}" Focusable="true" + MouseEnter="{Background=Red}" + MouseLeave="{Background=Blue}"> + <Label Margin="5" Text="Hello World" /> + </Border> +</VerticalStack> diff --git a/Samples/ShowCase/ShowCase.cs b/Samples/ShowCase/ShowCase.cs index cb094e4a..37582cfe 100644 --- a/Samples/ShowCase/ShowCase.cs +++ b/Samples/ShowCase/ShowCase.cs @@ -19,6 +19,13 @@ namespace ShowCase { class Showcase : SampleBaseForEditor { + DbgEvtType[] logEvts = { + DbgEvtType.MouseEnter, + DbgEvtType.MouseLeave, + DbgEvtType.WidgetMouseDown, + DbgEvtType.WidgetMouseUp, + DbgEvtType.WidgetMouseClick, + }; static void Main () { initDebugLog (); @@ -116,15 +123,13 @@ namespace ShowCase return true; case Key.F6: if (DebugLogRecording) { - DbgLogger.IncludeEvents = DbgEvtType.None; - DbgLogger.DiscardEvents = DbgEvtType.All; + DbgLogger.IncludedEvents.Clear(); if (DebugLogToFile && !string.IsNullOrEmpty(DebugLogFilePath)) DbgLogger.Save (this, DebugLogFilePath); DebugLogRecording = false; } else { DbgLogger.Reset (); - DbgLogger.IncludeEvents = RecordedEvents; - DbgLogger.DiscardEvents = DiscardedEvents; + DbgLogger.IncludedEvents = new List<DbgEvtType> (logEvts); DebugLogRecording = true; } return true; diff --git a/Samples/ShowCase/ui/Button.template b/Samples/ShowCase/ui/Button.template index c7e2fa06..9ef1001d 100644 --- a/Samples/ShowCase/ui/Button.template +++ b/Samples/ShowCase/ui/Button.template @@ -1,5 +1,5 @@ <?xml version="1.0"?> -<Border Background="{./Background}" MinimumSize="50,20" Name="Content" +<Border Background="{./Background}" MinimumSize="50,20" Name="Content" Width="Stretched" Foreground="Transparent" CornerRadius="{../CornerRadius}" BorderWidth="1" MouseEnter="{Foreground=vgradient|0:White|0.2:Grey|0.9:Grey|1:Black};{caption.Foreground=White}" MouseLeave="{Foreground=Transparent};{caption.Foreground=LightGrey}" diff --git a/Samples/ShowCase/ui/showcase.crow b/Samples/ShowCase/ui/showcase.crow index c64fa740..23368ced 100644 --- a/Samples/ShowCase/ui/showcase.crow +++ b/Samples/ShowCase/ui/showcase.crow @@ -25,7 +25,7 @@ <ListItem ContextCommands="{GetCommands}" Selected="{/exp.Background=${ControlHighlight}}" Unselected="{/exp.Background=Transparent}"> - <Expandable Name="exp" Caption="{Name}" MouseDoubleClick="/onClickForExpand" BubbleMouseEvent="MouseWheel|Keyboard|ButtonDown"> + <Expandable Name="exp" Caption="{Name}" MouseDoubleClick="/onClickForExpand" BubbleEvents="MouseWheel|Keyboard|MouseClick|ButtonDown"> <Template> <VerticalStack> <Border CornerRadius="2" Margin="0" Height="Fit" MouseDoubleClick="./onClickForExpand" @@ -44,7 +44,7 @@ <Label Text="{./Caption}"/> </HorizontalStack> </Border> - <Container Name="Content" Visible="false"/> + <Container Name="Content" Visible="false" BubbleEvents="MouseWheel|Keyboard"/> </VerticalStack> </Template> <HorizontalStack Height="Fit"> diff --git a/Samples/common/src/Editor.cs b/Samples/common/src/Editor.cs index e56914f8..0c702745 100644 --- a/Samples/common/src/Editor.cs +++ b/Samples/common/src/Editor.cs @@ -52,13 +52,13 @@ namespace Crow IEnumerable<MemberInfo> getAllCrowTypeMembers (string crowTypeName) { - Type crowType = IML.Instantiator.GetWidgetTypeFromName (crowTypeName); + Type crowType = IFace.GetWidgetTypeFromName (crowTypeName); return crowType.GetMembers (BindingFlags.Public | BindingFlags.Instance). Where (m=>((m is PropertyInfo pi && pi.CanWrite) || (m is EventInfo)) && m.GetCustomAttribute<XmlIgnoreAttribute>() == null); } MemberInfo getCrowTypeMember (string crowTypeName, string memberName) { - Type crowType = IML.Instantiator.GetWidgetTypeFromName (crowTypeName); + Type crowType = IFace.GetWidgetTypeFromName (crowTypeName); return crowType.GetMember (memberName, BindingFlags.Public | BindingFlags.Instance).FirstOrDefault (); } diff --git a/Samples/common/src/SampleBase.cs b/Samples/common/src/SampleBase.cs index b44bb8f5..3e0ef714 100644 --- a/Samples/common/src/SampleBase.cs +++ b/Samples/common/src/SampleBase.cs @@ -94,6 +94,17 @@ namespace Samples new ActionCommand("Action A", () => MessageBox.ShowModal(this, MessageBox.Type.Information, "context menu A clicked")) ); } + DeviceEventType deviceEventTypeEnum; + public DeviceEventType DeviceEventTypeEnum { + get => deviceEventTypeEnum; + set { + if (deviceEventTypeEnum == value) + return; + deviceEventTypeEnum = value; + NotifyValueChanged ("DeviceEventTypeEnum", deviceEventTypeEnum); + } + + } public int intValue = 500; VerticalAlignment currentVAlign; diff --git a/Samples/common/src/SampleBaseForEditor.cs b/Samples/common/src/SampleBaseForEditor.cs index e1cadc0a..a63ba54e 100644 --- a/Samples/common/src/SampleBaseForEditor.cs +++ b/Samples/common/src/SampleBaseForEditor.cs @@ -67,7 +67,7 @@ namespace Samples } public bool DebugLoggingEnabled => DbgLogger.IsEnabled; - public DbgEvtType RecordedEvents { + /*public DbgEvtType RecordedEvents { get => Configuration.Global.Get<DbgEvtType> (nameof (RecordedEvents)); set { if (RecordedEvents == value) @@ -88,7 +88,7 @@ namespace Samples DbgLogger.DiscardEvents = DiscardedEvents; NotifyValueChanged(DiscardedEvents); } - } + }*/ public bool DebugLogRecording { get => debugLogRecording; set { @@ -119,9 +119,6 @@ namespace Samples } protected static void initDebugLog () { - DbgLogger.IncludeEvents = DbgEvtType.None; - DbgLogger.DiscardEvents = DbgEvtType.All; - //DbgLogger.DiscardEvents = DbgEvtType.All; DbgLogger.ConsoleOutput = !Configuration.Global.Get<bool> (nameof (DebugLogToFile)); } diff --git a/Samples/common/ui/Interfaces/Experimental/buttonSizing.crow b/Samples/common/ui/Interfaces/Experimental/buttonSizing.crow new file mode 100644 index 00000000..04139b1b --- /dev/null +++ b/Samples/common/ui/Interfaces/Experimental/buttonSizing.crow @@ -0,0 +1,9 @@ +<VerticalStack Fit="true" Background="Onyx" Margin="0"> + <Button Caption='Ok' Background='MediumSeaGreen' Width="Stretched" MouseClick="{Background=Red}"> + <Template> + <Border Style="ButtonBorder" Background="{./Background}" Name="Content" CornerRadius="{../CornerRadius}" Width="Stretched"> + <Label Font="{./Font}" Name="caption" Margin="${ButtonCaptionMargin}" Foreground="{./Foreground}" Text="{./Caption}"/> + </Border> + </Template> + </Button> +</VerticalStack>
\ No newline at end of file diff --git a/Samples/common/ui/Interfaces/Experimental/enumSelector2.crow b/Samples/common/ui/Interfaces/Experimental/enumSelector2.crow new file mode 100644 index 00000000..adaf0870 --- /dev/null +++ b/Samples/common/ui/Interfaces/Experimental/enumSelector2.crow @@ -0,0 +1,18 @@ +<VerticalStack> + <Label Text="{DeviceEventTypeEnum}"/> + <EnumSelector Caption="Device Events:" EnumValue="{²DeviceEventTypeEnum}" ItemStyle="CheckBox3" Width="Fit" Background="Jet"> + <Template> + <Border Style="ControlBorder" Background="{./Background}" CornerRadius="{./CornerRadius}"> + <HorizontalStack> + <Label Text="{./Caption}"/> + <Popper Caption="{./EnumValue}" PopDirection="BottomLeft" > + <Template> + <Label Style="ControlCaption" Text="{./Caption}" Foreground="{./Foreground}" MinimumSize="80,1" TextAlignment="Center"/> + </Template> + <VerticalStack Fit="true" Name="Content" Background="Onyx" Width="{../PopWidth}" Margin="5"/> + </Popper> + </HorizontalStack> + </Border> + </Template> + </EnumSelector> +</VerticalStack> diff --git a/Samples/common/ui/Interfaces/Experimental/fileDialog.crow b/Samples/common/ui/Interfaces/Experimental/fileDialog.crow new file mode 100644 index 00000000..90f9c70c --- /dev/null +++ b/Samples/common/ui/Interfaces/Experimental/fileDialog.crow @@ -0,0 +1,17 @@ +<VerticalStack> + <HorizontalStack Height="Fit"> + <Label Text="Hover:" Width="50" Foreground="Grey"/> + <Label Text="{HoverWidget}" Font="mono, 8"/> + </HorizontalStack> + <HorizontalStack Height="Fit"> + <Label Text="Focus:" Width="50" Foreground="Grey"/> + <Label Text="{FocusedWidget}" Font="mono, 8"/> + </HorizontalStack> + <HorizontalStack Height="Fit"> + <Label Text="Active:" Width="50" Foreground="Grey"/> + <Label Text="{ActiveWidget}" Font="mono, 8"/> + </HorizontalStack> + <Container> + <FileDialog Focusable="true" Resizable="true"/> + </Container> +</VerticalStack>
\ No newline at end of file |