]> O.S.I.I.S - jp/crow.git/commitdiff
wip, save commit before trying to allow 'ItemTemplate' in style
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Mon, 13 Sep 2021 05:27:50 +0000 (05:27 +0000)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Mon, 13 Sep 2021 05:27:50 +0000 (05:27 +0000)
23 files changed:
Crow/Default.style
Crow/Templates/Button.template
Crow/Templates/DefaultItem.template
Crow/Templates/Expandable.template
Crow/Templates/WindowButton.template
Crow/Templates/imgItem.template
Crow/src/IML/Instantiator.cs
Crow/src/IToggle.cs
Crow/src/ItemTemplate.cs
Crow/src/Widgets/DockWindow.cs
Crow/src/Widgets/GroupBase.cs
Crow/src/Widgets/TemplatedControl.cs
Crow/src/Widgets/TemplatedGroup.cs
Crow/src/styling/StyleReader.cs
Samples/Directory.Build.props
Samples/ShowCase/ShowCase.csproj
Samples/ShowCase/ui/CheckBox2.imlt [new file with mode: 0644]
Samples/ShowCase/ui/ShowCase.style
Samples/ShowCase/ui/showcase.crow
Samples/common/samples.style
Samples/common/src/SampleBase.cs
Samples/common/ui/Interfaces/Experimental/icobut.crow [new file with mode: 0644]
Samples/common/ui/Interfaces/Experimental/templatedControlMargin.crow [new file with mode: 0644]

index 16d64f5735b02a407bed2745b29c81622eeb8745..e89da49ffb357469e40b65ae975b19876e6c9211 100644 (file)
@@ -7,6 +7,8 @@ ControlCaptionHoverColor = "White";
 ControlCornerRadius = "0";
 ControlInsideMargin = "1";
 
+ButtonCaptionMargin = "6";
+
 IconSize = "11";
 IconMargin = "1";
 ToggleIconSize = "16";
@@ -77,6 +79,14 @@ Button {
        Height          = "Fit";
        Width           = "Fit";
 }
+ButtonBorder {
+       BorderWidth="1";
+       Foreground="Transparent";
+       MouseEnter="{Foreground=vgradient|0:White|0.2:Grey|0.9:Grey|1:Black}";
+       MouseLeave="{Foreground=Transparent}";
+       MouseDown="{Foreground=vgradient|0:Black|0.05:Grey|0.85:Grey|1:White}";
+       MouseUp="{Foreground=vgradient|0:White|0.2:Grey|0.9:Grey|1:Black}";
+}
 Label {
        Height = "Fit";
        Width = "Fit";
index daa09c6a739f946d55591dd0ecd4b1aea9fb13be..9ad621d968077558e297b9045b0e850ee922dc6f 100644 (file)
@@ -1,9 +1,4 @@
 <?xml version="1.0"?>
-<Border Background="{./Background}" Name="Content" 
-       Foreground="Transparent" CornerRadius="{../CornerRadius}" BorderWidth="1"
-       MouseEnter="{Foreground=vgradient|0:White|0.2:Grey|0.9:Grey|1:Black}"
-       MouseLeave="{Foreground=Transparent}"
-       MouseDown="{Foreground=vgradient|0:Black|0.05:Grey|0.85:Grey|1:White}"
-       MouseUp="{Foreground=vgradient|0:White|0.2:Grey|0.9:Grey|1:Black}" >
-       <Label Font="{./Font}" Name="caption" Margin="6" Foreground="{./Foreground}" Text="{./Caption}"/>
+<Border Style="ButtonBorder" Background="{./Background}" Name="Content" CornerRadius="{../CornerRadius}" >
+       <Label Font="{./Font}" Name="caption" Margin="${ButtonCaptionMargin}" Foreground="{./Foreground}" Text="{./Caption}"/>
 </Border>
index f2d7102d42d2b38b5d2772e48e1bf718b7053bba..c05a3def88366078f9306165277ee97ce16dd16f 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<ListItem Height="Fit" Margin="0" Focusable="true" HorizontalAlignment="Left" 
+<ListItem Height="Fit" Margin="0" Focusable="true" HorizontalAlignment="Left"
                                Selected = "{Background=${ControlHighlight}}"
                                Unselected = "{Background=Transparent}">
        <Label Text="{}" HorizontalAlignment="Left" />
index efa24b921ff08d230463e19ecbc7843726340241..fc6606440811c19e375019349b494f640f6134c4 100644 (file)
@@ -5,7 +5,7 @@
                        <Image Style="Icon" MouseDown="./onClickForExpand"
                                        MouseEnter="{Background=White}" MouseLeave="{Background=Transparent}"
                                        Background="{./Background}"
-                                       Path="#Crow.Icons.expandable.svg" Visible="{./IsExpandable}"    SvgSub="{./IsExpanded}" />                      
+                                       Path="#Crow.Icons.expandable.svg" Visible="{./IsExpandable}"    SvgSub="{./IsExpanded}" />
                        <Label Style="ControlCaption" Text="{./Caption}"/>
                </HorizontalStack>
                <Container Name="Content" Visible="false"/>
index 19ce8f900e0d4ddafa46a31ea4291fdfae402fa4..f03caf671e292a1669b815ad96ac47e7822a86b7 100644 (file)
@@ -3,7 +3,7 @@
        <Template>
                <Border Style="WindowIconBorder" IsVisible="{./IsEnabled}">
                        <Image Path="{./Icon}" Tooltip="{./Caption}"/>
-               </Border>                                                       
+               </Border>
        </Template>
 </Button>
 
index 9dbf23d5f7eea4a531da361b23f7ea0ae471d22d..a0861fdb50ce3b675d34f725affffcfa3eac29c0 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-       <VerticalStack Width="0" Height="-1" Focusable="true"                   
+       <VerticalStack Width="0" Height="-1" Focusable="true"
                        MouseEnter="{Background=RoyalBlue}"
                        MouseLeave="{Background=Transparent}">
                <Image Width="-1" Height="-1" Path="{FullName}" MaximumSize="80,80"/>
index 7a2472ae6fc77081b1f8cbd7b26b17c48203a00e..087d4f97826046667f029ddc1575513bb047524f 100644 (file)
@@ -26,14 +26,14 @@ namespace Crow.IML {
        public delegate object InstanciatorInvoker(Interface iface);
 
        /// <summary>
-       /// Reflexion being very slow, the settings of the starting values for widgets are set by a dynamic method.
+       /// Reflection being very slow, the settings of the starting values for widgets are set by a dynamic method.
        /// This method is created on the first instacing and is recalled for further widget instancing.
-       /// 
+       ///
        /// It includes:
        ///     - XML values setting
        ///     - Default values (appearing as attribute in C#)  loading
        ///     - Styling
-       /// 
+       ///
        /// Their are stored in the Interface with their path as key, and inlined template
        /// and itemtemplate are stored with a generated uuid
        /// </summary>
@@ -62,7 +62,7 @@ namespace Crow.IML {
 #endif
 
                #region CTOR
-               static XmlReaderSettings xmlReaderSettings;             
+               static XmlReaderSettings xmlReaderSettings;
                static string NT_template, NT_iTemp, NT_style, NT_name, NT_dataSource, NT_dataSourceType;
                static Instantiator () {
                        NameTable names =  new NameTable ();
@@ -76,13 +76,13 @@ namespace Crow.IML {
 
                        xmlReaderSettings = new XmlReaderSettings ();
                        xmlReaderSettings.NameTable = names;
-                       
+
                }
                /// <summary>
                /// Initializes a new instance of the Instantiator class.
                /// </summary>
                public Instantiator (Interface _iface, string path) : this (_iface, _iface.GetStreamFromPath(path), path) {
-                       
+
                }
                /// <summary>
                /// Initializes a new instance of the Instantiator class.
@@ -231,7 +231,7 @@ namespace Crow.IML {
                        ctx.curLine += li.LineNumber - 1;
                        #endif
 
-                       string tmpXml = reader.ReadOuterXml ();                 
+                       string tmpXml = reader.ReadOuterXml ();
 
                        if (ctx.nodesStack.Peek().HasTemplate)
                                emitTemplateLoad (ctx, tmpXml);
@@ -246,7 +246,7 @@ namespace Crow.IML {
                /// <returns>the string triplet dataType, itemTmpID read as attribute of this tag</returns>
                /// <param name="reader">current xml text reader</param>
                /// <param name="itemTemplatePath">file containing the templates if its a dedicated one</param>
-               string[] parseItemTemplateTag (IMLContext ctx, XmlReader reader, string itemTemplatePath = "") {
+               string[] parseItemTemplateTag (XmlReader reader, string itemTemplatePath = "") {
                        string dataType = "default", datas = "", path = "", dataTest = "TypeOf";
                        while (reader.MoveToNextAttribute ()) {
                                if (reader.Name == "DataType")
@@ -270,7 +270,7 @@ namespace Crow.IML {
                        } else {
                                if (!reader.IsEmptyElement)
                                        throw new Exception ("ItemTemplate with Path attribute set may not include sub nodes");
-                               itemTmpID += path+dataType+datas;
+                               itemTmpID += $"{path}{dataType}{datas}";
                                if (!iface.ItemTemplates.ContainsKey (itemTmpID))
                                        iface.ItemTemplates [itemTmpID] =
                                                new ItemTemplate (iface, path, dataTest, dataType, datas);
@@ -308,7 +308,7 @@ namespace Crow.IML {
                                                reader.Read ();
                                                readChildren (reader, ctx, -1);
                                        } else if (reader.Name == NT_iTemp)
-                                               itemTemplateIds.Add (parseItemTemplateTag (ctx, reader));                                       
+                                               itemTemplateIds.Add (parseItemTemplateTag (reader));
                                }
 
                                if (!inlineTemplate) {//load from path or default template
@@ -331,7 +331,7 @@ namespace Crow.IML {
                                                        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)) {                                                                        
+                                                               using (XmlReader itr = XmlReader.Create (stream, itrSettings)) {
                                                                        while (itr.Read ()) {
                                                                                if (!itr.IsStartElement ())
                                                                                        continue;
@@ -343,7 +343,7 @@ namespace Crow.IML {
                                                                                                itemTemplateIds.Add (new string [] { "default", itemTemplatePath, "", "TypeOf" });
                                                                                                break;//we should be at the end of the file
                                                                                        }
-                                                                                       itemTemplateIds.Add (parseItemTemplateTag (ctx, itr, itemTemplatePath));
+                                                                                       itemTemplateIds.Add (parseItemTemplateTag (itr, itemTemplatePath));
                                                                                }
                                                                        }
                                                                }
@@ -356,7 +356,7 @@ namespace Crow.IML {
                                //add the default item template if no default is defined
                                if (!itemTemplateIds.Any(ids=>ids[0] == "default"))
                                        itemTemplateIds.Add (new string [] { "default", "#Crow.DefaultItem.template", "", "TypeOf"});
-                               //get item templates 
+                               //get item templates
                                foreach (string [] iTempId in itemTemplateIds) {
                                        ctx.il.Emit (OpCodes.Ldloc_0);//load TempControl ref
                                        ctx.il.Emit (OpCodes.Ldfld, CompilerServices.fldItemTemplates);//load ItemTemplates dic field
@@ -433,12 +433,12 @@ namespace Crow.IML {
 #endif
                                        }
                                        //check for dataSourceType, if set, datasource bindings will use direct setter/getter
-                                       //instead of reflexion
+                                       //instead of reflection
                                        string dataSourceType = reader.GetAttribute (NT_dataSourceType);
                                        if (string.IsNullOrEmpty (dataSourceType)) {
                                                //if not set but dataSource is not null, reset dsType to null
                                                string ds = reader.GetAttribute (NT_dataSource);
-                                               if (!string.IsNullOrEmpty (ds)) 
+                                               if (!string.IsNullOrEmpty (ds))
                                                        ctx.SetDataSourceTypeForCurrentNode (null);
                                        } else
                                                ctx.SetDataSourceTypeForCurrentNode(CompilerServices.getTypeFromName (dataSourceType));
@@ -447,7 +447,6 @@ namespace Crow.IML {
                 ctx.il.Emit (OpCodes.Call, CompilerServices.miLoadDefaultVals);
 #endregion
 
-
                                #region Attributes reading
                                if (reader.HasAttributes) {
 
@@ -477,7 +476,7 @@ namespace Crow.IML {
                                                                        if (string.IsNullOrEmpty (cstId) || !iface.StylingConstants.ContainsKey (cstId))
                                                                                throw new Exception ("undefined constant id: " + cstId);
                                                                        styledValue.Append (iface.StylingConstants [cstId]);
-                                                                       continue; 
+                                                                       continue;
                                                                }
                                                        }
                                                        styledValue.Append (imlValue [vPtr++]);
@@ -552,10 +551,10 @@ namespace Crow.IML {
                                        if (t == null)
                                                throw new Exception (reader.Name + " type not found");
                                        ConstructorInfo ci = t.GetConstructor (
-                                                                    BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,  
+                                                                    BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,
                                                null, Type.EmptyTypes, null);
                                        if (ci == null)
-                                               throw new Exception ("No default parameterless constructor found in " + t.Name);                                        
+                                               throw new Exception ("No default parameterless constructor found in " + t.Name);
                                        ctx.il.Emit (OpCodes.Newobj, ci);
                                        ctx.il.Emit (OpCodes.Stloc_0);//child is now loc_0
                                        CompilerServices.emitSetCurInterface (ctx.il);
@@ -804,7 +803,7 @@ namespace Crow.IML {
                                il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
                                il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);//load handler method name
                                il.Emit (OpCodes.Call, CompilerServices.miGetMethInfoWithRefx);
-                               il.Emit (OpCodes.Stloc_0);//save MethodInfo                                          
+                               il.Emit (OpCodes.Stloc_0);//save MethodInfo
                 il.Emit (OpCodes.Ldloc_0);//push mi for test if null
                 il.Emit (OpCodes.Brfalse, cancel);//cancel if null
 
@@ -821,19 +820,19 @@ namespace Crow.IML {
 
                 il.Emit (OpCodes.Call, CompilerServices.miCreateBoundDel);
                 il.Emit (OpCodes.Callvirt, sourceEvent.AddMethod);//call add event
-                                          
+
                 System.Reflection.Emit.Label finish = il.DefineLabel ();
                 il.Emit (OpCodes.Br, finish);
                 il.MarkLabel (cancel);
-                               //#if DEBUG_BINDING     
-                               //TODO: try to print datasource type in the error message                       
+                               //#if DEBUG_BINDING
+                               //TODO: try to print datasource type in the error message
                                il.EmitWriteLine (string.Format ("Handler method '{0}' for '{1}' NOT FOUND in new dataSource", bindingDef.TargetMember, sourceEvent.Name));
                                //#endif
                                il.MarkLabel (finish);
                                #if DEBUG_BINDING
                                il.EmitWriteLine (string.Format ("Handler method '{0}' for '{1}' FOUND in new dataSource", bindingDef.TargetMember, sourceEvent.Name));
                                #endif
-                                              
+
                                il.Emit (OpCodes.Ret);
 
                                //store dschange delegate in instatiator instance for access while instancing graphic object
@@ -1314,10 +1313,10 @@ namespace Crow.IML {
                }
 
                /// <summary>
-               /// create the valuechanged handler and the datasourcechanged handler and return the 
+               /// create the valuechanged handler and the datasourcechanged handler and return the
                /// DataSourceChange delegate
                /// </summary>
-               public Delegate emitDataSourceBindings (PropertyInfo piSource, BindingDefinition bindingDef){           
+               public Delegate emitDataSourceBindings (PropertyInfo piSource, BindingDefinition bindingDef){
 
 #if DEBUG_BINDING_FUNC_CALLS
                        Console.WriteLine ($"emitDataSourceBindings: {bindingDef}");
@@ -1431,7 +1430,7 @@ namespace Crow.IML {
                                        il.Emit (OpCodes.Ldloc_2);//load datasource
                                        il.Emit (OpCodes.Ldloc_3);//load first memberInfo
                                        il.Emit (OpCodes.Call, CompilerServices.miGetValWithRefx);//get first member level
-                               } 
+                               }
                                il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);//load member name
                                il.Emit (OpCodes.Call, CompilerServices.miGetMembIinfoWithRefx);
                                il.Emit (OpCodes.Stloc_1);//save memberInfo
index 54564be48f85614f7d635b8649b8717849529141..6a47b40478b86baf99f14e90853cdc4b228966de 100644 (file)
@@ -11,7 +11,7 @@ namespace Crow
                event EventHandler ToggleOn;
                event EventHandler ToggleOff;
                BooleanTestOnInstance IsToggleable { get; set; }
-               
+
                bool IsToggled {
                        get;
                        set;
index dc8e29c07a5a5222ff134461ef62cd6bf498bdbe..9fcbd7fbc21d2ffef14b6a69d4cf6d40cee3fa6c 100644 (file)
@@ -22,16 +22,16 @@ namespace Crow
 
        /// <summary>
        /// Derived from Instantiator with sub data fetching facilities for hierarchical data access.
-       /// 
+       ///
        /// ItemTemplate stores the dynamic method for instantiating the control tree defined in a valid IML file.
-       /// 
+       ///
        /// </summary>
        public class ItemTemplate : Instantiator {
                #if DESIGN_MODE
-               public void getIML (System.Xml.XmlDocument doc, System.Xml.XmlNode parentElem){         
+               public void getIML (System.Xml.XmlDocument doc, System.Xml.XmlNode parentElem){
                        if (sourcePath == "#Crow.DefaultItem.template")
                                return;
-                       
+
                        XmlElement xe = doc.CreateElement("ItemTemplate");
                        XmlAttribute xa = null;
 
@@ -62,10 +62,10 @@ namespace Crow
                                xa.Value = fetchMethodName;
                                xe.Attributes.Append (xa);
                        }
-                               
+
                        parentElem.AppendChild (xe);
 
-                               
+
                }
                #endif
 
@@ -137,14 +137,14 @@ namespace Crow
                        //DM is bound to templatedGroup root (arg0)
                        //arg1 is the sender of the expand event
                        DynamicMethod dm = new DynamicMethod ("dyn_expand_" + fetchMethodName,
-                               typeof (void), args, typeof(TemplatedGroup), true);                     
+                               typeof (void), args, typeof(TemplatedGroup), true);
 
                        System.Reflection.Emit.Label gotoEnd;
                        System.Reflection.Emit.Label ifDataIsNull;
                        System.Reflection.Emit.Label gotoItemsContainerNotFound;
 
-                       ILGenerator il = dm.GetILGenerator (256);                       
-                       
+                       ILGenerator il = dm.GetILGenerator (256);
+
                        il.DeclareLocal(typeof(Widget));
                        il.DeclareLocal(typeof(IEnumerable));
 
@@ -182,7 +182,7 @@ namespace Crow
                                        il.Emit (OpCodes.Ldstr, fetchMethodName);
                                        il.Emit (OpCodes.Call, CompilerServices.miGetDataTypeAndFetch);
                                }else
-                                       emitGetSubData(il, dataType);                   
+                                       emitGetSubData(il, dataType);
                        }
                        il.Emit (OpCodes.Stloc_1);//save and reload datas IEnumerable for registering IObsList
                        il.Emit (OpCodes.Ldloc_1);
@@ -220,7 +220,7 @@ namespace Crow
                        //dm is unbound, arg0 is instance of Item container to expand
                        dm = new DynamicMethod ("dyn_count_" + fetchMethodName,
                                typeof (bool), new Type[] {typeof(object)}, true);
-                       il = dm.GetILGenerator (256);                   
+                       il = dm.GetILGenerator (256);
                        System.Reflection.Emit.Label end = il.DefineLabel ();
                        System.Reflection.Emit.Label test = il.DefineLabel ();
 
@@ -236,18 +236,18 @@ namespace Crow
                                        il.Emit (OpCodes.Ldstr, fetchMethodName);
                                        il.Emit (OpCodes.Call, CompilerServices.miGetDataTypeAndFetch);
                                }else
-                                       emitGetSubData(il, dataType);                   
-                       }                       
+                                       emitGetSubData(il, dataType);
+                       }
                        il.Emit (OpCodes.Isinst, typeof(System.Collections.ICollection));
                        il.Emit (OpCodes.Dup);//duplicate children for testing if it's a collection for childs counting
                        il.Emit (OpCodes.Brtrue, test);//if true, jump to perform count
                        il.Emit (OpCodes.Pop);//pop null
-                       il.Emit (OpCodes.Ldc_I4_0);//push false                 
+                       il.Emit (OpCodes.Ldc_I4_0);//push false
                        il.Emit (OpCodes.Br, end);
 
                        il.MarkLabel (test);
 
-                       il.Emit (OpCodes.Callvirt, CompilerServices.miGetColCount);                     
+                       il.Emit (OpCodes.Callvirt, CompilerServices.miGetColCount);
                        il.Emit (OpCodes.Ldc_I4_0);
                        il.Emit (OpCodes.Cgt);
 
index 763da1aa63f0e96af8cabe079ed7be64497d3e88..326bfce48ecf0c644b61da9b4864a2115fe8c168 100644 (file)
@@ -102,7 +102,7 @@ namespace Crow
                                NotifyValueChangedAuto (floatingGroup);
                        }
                }
-               
+
                bool tryGetTargetDockStack (DockWindow dw, out DockStack ds) {
                        if (dw.Parent is DockStack dwp)
                                ds = dwp;
@@ -114,12 +114,12 @@ namespace Crow
                }
                bool dockParentParent = false;
                public override void onDrag (object sender, MouseMoveEventArgs e)
-               {                       
+               {
                        if (!freezeDockState && isDocked)
                                checkUndock (e.Position);
                        else
                                moveAndResize (e.XDelta, e.YDelta, currentDirection);
-                       
+
                        base.onDrag (sender, e);
 
                        if (freezeDockState || isDocked)
@@ -146,7 +146,7 @@ namespace Crow
                                } else {
                                        dwCb = r;
                                        dwCb.Inflate (-4,-4);
-                                                                               
+
                                        if (tryGetTargetDockStack (dw, out DockStack targetStack)) {
                                                Console.WriteLine ($"exterior: {!dwCb.ContainsOrIsEqual (m)} targetStack.Parent: {targetStack.Parent.GetType()}");
                                                if (dwCb.ContainsOrIsEqual (m)) {
@@ -157,7 +157,7 @@ namespace Crow
                                                        r = targetStack.ScreenCoordinates (targetStack.LastPaintedSlot);
                                                } else
                                                        r = dw.ScreenCoordinates (dw.LastPaintedSlot);
-                                               
+
                                                targetStack.onDragMouseMove (this, e);
                                        } else
                                                System.Diagnostics.Debugger.Break ();
@@ -241,7 +241,7 @@ namespace Crow
                                        else if (tryGetTargetDockStack (dw, out DockStack targetStack)) {
                                                if (dockParentParent)
                                                        targetStack = targetStack.Parent as DockStack;
-                                               Dock (targetStack);                                             
+                                               Dock (targetStack);
                                        }else
                                                System.Diagnostics.Debugger.Break ();
                                }else
@@ -274,8 +274,8 @@ namespace Crow
                                } else if (Parent is DockStack ds) {
                                        ds.Undock (this);
                                } else
-                                       throw new Exception ("docking error");                          
-                               
+                                       throw new Exception ("docking error");
+
                                IFace.AddWidget (this);
 
                                Left = IFace.MousePosition.X - 10;
@@ -335,11 +335,11 @@ namespace Crow
                                        target.NotifyValueChanged ("IsDockedInStack", false);
 
                                        IsDocked = true;
-                               }                               
+                               }
                        }
                }
                void Dock (DockStack target){
-                       lock (IFace.UpdateMutex) {                              
+                       lock (IFace.UpdateMutex) {
                                dock ();
 
                                target.Dock (this);
@@ -356,7 +356,6 @@ namespace Crow
                internal string GetDockConfigString () =>
                        string.Format($"WIN;{Name};{Width};{Height};{DockingPosition};{savedSlot};{wasResizable};");
 
-               
                public string FloatingConfigString =>
                        $"{Name};{Left};{Top};{Width};{Height};{FreezeDockState};{Resizable}";
                public static DockWindow CreateFromFloatingConfigString (Interface iface, ReadOnlySpan<char> conf, object datasource = null) {
@@ -374,7 +373,7 @@ namespace Crow
                        dw.Height = Measure.Parse (conf.Slice(0, i).ToString());
                        conf = conf.Slice (i + 1); i = conf.IndexOf (';');
                        dw.FreezeDockState = bool.Parse (conf.Slice(0, i).ToString());
-                       
+
                        dw.Resizable = bool.Parse (conf.Slice (i + 1).ToString());
                        dw.DataSource = datasource;
 
index 13d99f0aa4c13a3d0c4341c38382df8be9164925..8c98d0b612a0fe606450f29d6bc0a1f93b72d648 100644 (file)
@@ -37,7 +37,7 @@ namespace Crow
                                return;
                        base.getIML (doc, parentElem);
                        foreach (Widget g in Children) {
-                               g.getIML (doc, parentElem.LastChild);   
+                               g.getIML (doc, parentElem.LastChild);
                        }
                }
                #endif
@@ -94,7 +94,7 @@ namespace Crow
                                return;
                        }
                        childrenRWLock.EnterWriteLock ();
-                       try {   
+                       try {
                                g.Parent = this;
                                Children.Insert (idx, g);
                        } finally {
@@ -129,7 +129,7 @@ namespace Crow
                        try {
                                foreach (Widget g in Children) {
                                        if (g.localDataSourceIsNull & g.localLogicalParentIsNull)
-                                               g.OnDataSourceChanged (g, e);   
+                                               g.OnDataSourceChanged (g, e);
                                }
                        } finally {
                                childrenRWLock.ExitReadLock ();
@@ -161,7 +161,7 @@ namespace Crow
                                }
                        } finally {
                                childrenRWLock.ExitWriteLock ();
-                       }                       
+                       }
                }
 
                #region GraphicObject overrides
@@ -186,7 +186,7 @@ namespace Crow
                                childrenRWLock.ExitReadLock ();
                        }
                }
-               public override T FindByType<T> () 
+               public override T FindByType<T> ()
                {
                        if (this is T t)
                                return t;
@@ -224,7 +224,7 @@ namespace Crow
                {
                        DbgLogger.StartEvent (DbgEvtType.GODraw, this);
 
-                       base.onDraw (gr);                       
+                       base.onDraw (gr);
 
                        if (ClipToClientRect) {
                                gr.Save ();
@@ -236,7 +236,7 @@ namespace Crow
                        childrenRWLock.EnterReadLock ();
                        try
                        {
-                               for (int i = 0; i < Children.Count; i++) 
+                               for (int i = 0; i < Children.Count; i++)
                                        Children[i].Paint (gr);
                        } finally {
                                childrenRWLock.ExitReadLock ();
@@ -256,7 +256,7 @@ namespace Crow
                                                gr.Rectangle(Clipping.GetRectangle(i));
                                        gr.ClipPreserve();
                                        gr.Operator = Operator.Clear;
-                                       gr.Fill();                                      
+                                       gr.Fill();
                                        gr.Operator = Operator.Over;
 
                                        base.onDraw (gr);
@@ -291,7 +291,7 @@ namespace Crow
                                Console.WriteLine("GROUP REPAINT WITH EMPTY CLIPPING");*/
                        //paintCache (ctx, Slot + Parent.ClientRectangle.Position);
                        base.UpdateCache (ctx);
-                       DbgLogger.EndEvent(DbgEvtType.GOUpdateCache);                           
+                       DbgLogger.EndEvent(DbgEvtType.GOUpdateCache);
                }
                #endregion
 
index 4a1c320a466d9aaccec9e97ec355aaa914f7a06a..a50352ee01fac5ce18437f4979672f885d7e40be 100644 (file)
@@ -88,7 +88,7 @@ namespace Crow
                /// <param name="gr">Backend context</param>
                protected override void onDraw (Context gr)
                {
-                       DbgLogger.StartEvent (DbgEvtType.GODraw, this);                 
+                       DbgLogger.StartEvent (DbgEvtType.GODraw, this);
 
                        if (ClipToClientRect) {
                                //clip to client zone
@@ -96,7 +96,7 @@ namespace Crow
                                CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius);
                                gr.Clip ();
                        }
-                       
+
                        child?.Paint (gr);
 
                        if (ClipToClientRect)
@@ -108,6 +108,7 @@ namespace Crow
 
                /// <summary>
                /// Loads the template. Each TemplatedControl MUST provide a default template
+               /// or have an inlined template in iml.
                /// It must be an embedded ressource with ID = fullTypeName.template
                /// Entry assembly is search first, then the one where the type is defined
                /// </summary>
@@ -116,11 +117,11 @@ namespace Crow
                {
                        if (this.child != null)//template change, bindings has to be reset
                                this.ClearTemplateBinding();
-                       
+
                        if (template == null) {
                                string defTmpId = this.GetType ().FullName + ".template";
                                if (!IFace.DefaultTemplates.ContainsKey (defTmpId)) {
-                                       
+
                                        Stream s = IFace.GetStreamFromPath ("#" + defTmpId);
                                        if (s == null)
                                                throw new Exception (string.Format ("No default template found for '{0}'", this.GetType ().FullName));
index 11a206e98cab62660d2bb25bf65c2e9fc9e2eb49..9ec8cb5ef48c0998689072c9d3d39ffc0a1c1dfe 100644 (file)
@@ -22,12 +22,12 @@ namespace Crow {
                        base.getIML (doc, parentElem);
 
                        if (string.IsNullOrEmpty(_itemTemplate)) {
-                               foreach (ItemTemplate it in ItemTemplates.Values) 
-                                       it.getIML (doc, parentElem.LastChild);                          
+                               foreach (ItemTemplate it in ItemTemplates.Values)
+                                       it.getIML (doc, parentElem.LastChild);
                        }
 
                        foreach (Widget g in Items) {
-                               g.getIML (doc, parentElem.LastChild);   
+                               g.getIML (doc, parentElem.LastChild);
                        }
                }
                #endif
@@ -84,13 +84,13 @@ namespace Crow {
                internal List<Widget> nodes = new List<Widget>();//TODO:close time tracking
                /// <summary>
                /// Item templates file path, on disk or embedded.
-               /// 
+               ///
                /// ItemTemplate file may contains either a single template without the
                /// ItemTemplate enclosing tag, or several item templates each enclosed
                /// in a separate tag.
-               /// </summary>          
+               /// </summary>
                public string ItemTemplate {
-                       get { return _itemTemplate; }
+                       get => _itemTemplate;
                        set {
                                if (value == _itemTemplate)
                                        return;
@@ -150,7 +150,7 @@ namespace Crow {
                        set {
                                if (selectedItem == value)
                                        return;
-                               
+
                                if (selectedItem is ISelectable oldItem)
                                        oldItem.IsSelected = false;
 
@@ -195,7 +195,7 @@ namespace Crow {
                                        ol.ListRemove -= Ol_ListRemove;
                                        ol.ListEdit -= Ol_ListEdit;
                                        ol.ListClear -= Ol_ListClear;
-                                       
+
                                }
 
                                data = value;
@@ -218,11 +218,11 @@ namespace Crow {
 
                                if (data is ICollection c) {
                                        if (c.Count == 0) {
-                                               NotifyValueChanged ("HasItems", false);         
+                                               NotifyValueChanged ("HasItems", false);
                                                return;
                                        }
                                }
-                               
+
                                if (useLoadingThread) {
                                        loadingThread = new CrowThread (this, loading);
                                        loadingThread.Finished += (object sender, EventArgs e) => (sender as TemplatedGroup).Loaded.Raise (sender, e);
@@ -260,7 +260,7 @@ namespace Crow {
                        } else
                                loadItem (e.Element, itemsContainer, dataTest);
                }
-               void Ol_ListEdit (object sender, ListChangedEventArg e) {                       
+               void Ol_ListEdit (object sender, ListChangedEventArg e) {
                        if (this.isPaged) {
                                throw new NotImplementedException ();
                        } else if (e.Index<itemsContainer.Children.Count)
@@ -268,7 +268,7 @@ namespace Crow {
 
                }
                void Ol_ListClear (object sender, ListClearEventArg e) {
-                       cancelLoadingThread ();                 
+                       cancelLoadingThread ();
                        if (this.isPaged) {
                                throw new NotImplementedException ();
                        } else {
@@ -281,13 +281,13 @@ namespace Crow {
                        SelectedItemChanged.Raise (this, new SelectionChangeEventArgs (SelectedItem));
                }
                public virtual void AddItem(Widget g){
-                       
+
                        itemsContainer.AddChild (g);
                        g.LogicalParent = this;
                        NotifyValueChanged ("HasChildren", true);
                }
                public virtual void RemoveItem(Widget g, bool disposeChild = true)
-               {                                                       
+               {
                        if (disposeChild)
                                itemsContainer.DeleteChild (g);
                        else
@@ -367,7 +367,7 @@ namespace Crow {
                        } catch (Exception ex) {
 /*                             while (Monitor.IsEntered (IFace.UpdateMutex))
                                        Monitor.Exit (IFace.UpdateMutex);
-                               while (Monitor.IsEntered (IFace.LayoutMutex)) 
+                               while (Monitor.IsEntered (IFace.LayoutMutex))
                                        Monitor.Exit (IFace.LayoutMutex);*/
                                System.Diagnostics.Debug.WriteLine ("loading thread aborted: " + ex.ToString());
                        } finally {
@@ -401,7 +401,7 @@ namespace Crow {
                        while (Monitor.IsEntered (IFace.LayoutMutex)) {
                                Monitor.Exit (IFace.LayoutMutex);
                                layoutMx++;
-                       }*/                     
+                       }*/
 
                        loadingThread.Cancel ();
 
@@ -411,7 +411,7 @@ namespace Crow {
                                Monitor.Enter (IFace.UpdateMutex);*/
 
                        loadingThread = null;
-                       
+
                        DbgLogger.EndEvent (DbgEvtType.TGCancelLoadingThread);
                }
                void loadPage(IEnumerable _data, Group page, string _dataTest)
@@ -464,7 +464,7 @@ namespace Crow {
                        string itempKey = dataType.FullName;
 
                        //if item template selection is not done depending on the type of item
-                       //dataTest must contains a member name of the item 
+                       //dataTest must contains a member name of the item
                        if (_dataTest != "TypeOf") {
                                try {
                                        itempKey = CompilerServices.getValue (dataType, o, _dataTest)?.ToString ();
@@ -499,7 +499,7 @@ namespace Crow {
                                        Thread.Sleep(1);
                                }
                        }
-                       
+
                        try {
                                g = iTemp.CreateInstance();
                                #if DESIGN_MODE
@@ -518,11 +518,11 @@ namespace Crow {
 
                        if (iTemp.Expand != null) {
                                IToggle toggle = g as IToggle;
-                               
+
                                if (toggle == null)
                                        toggle = g.FindByType<IToggle> ();
-                                       
-                               if (toggle != null) { 
+
+                               if (toggle != null) {
                                        toggle.ToggleOn += iTemp.Expand;
                                        toggle.IsToggleable = iTemp.HasSubItems;
                                }
@@ -591,7 +591,7 @@ namespace Crow {
                }
                internal virtual void itemClick(object sender, MouseButtonEventArgs e){
                        //SelectedIndex = (int)((IList)data)?.IndexOf((sender as Widget).DataSource);
-                       
+
                        if (sender is ISelectable nli) {
                                nli.IsSelected = true;
                                return;
@@ -599,7 +599,7 @@ namespace Crow {
                        selectedItemContainer = sender as Widget;
                        if (selectedItemContainer == null)
                                return;
-                       SelectedItem = selectedItemContainer.DataSource;                        
+                       SelectedItem = selectedItemContainer.DataSource;
                }
 
                bool emitHelperIsAlreadyExpanded (Widget go){
@@ -642,11 +642,11 @@ namespace Crow {
                                ol.ListEdit += (sender, e) => itemsContainer.Children [e.Index].DataSource = e.Element;
                                ol.ListClear += (sender, e) => {        lock (IFace.UpdateMutex)
                                                                                                                itemsContainer.ClearChildren ();};
-                               
+
                        }*/
                }
                void onDatasChanged (object sender, ValueChangeEventArgs e) {
-                       
+
                }
 
                public override void onKeyDown(object sender, KeyEventArgs e)
index 46931edfe1bacc82cdd40a3a3de0ebd134a6ec6a..2df90a22e09c3e171a9819bed5f0efbfaf231389 100644 (file)
@@ -134,7 +134,7 @@ namespace Crow
                                                if (c == '$') {
                                                        if (PeekChar () == '{') {
                                                                ReadChar ();
-                                                               //constant replacement                                                          
+                                                               //constant replacement
                                                                while (!EndOfStream) {
                                                                        c = ReadChar ();
                                                                        if (c == '}')
index 3cdb4a645ad54c9793cc0c04b2263907163f3e10..8e2a39cdb1e4755577d84c4696060f58a2bdc3a7 100644 (file)
@@ -3,13 +3,13 @@
                <TargetFrameworks>netcoreapp3.1</TargetFrameworks>
                <!--<TargetFrameworks>net5</TargetFrameworks>-->
                <OutputType>WinExe</OutputType>
-               
+
                <SolutionDir>$(MSBuildThisFileDirectory)..\</SolutionDir>
                <OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
                <IntermediateOutputPath>$(SolutionDir)build\obj\$(Configuration)\</IntermediateOutputPath>
-               
+
                <!--<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>-->
-               
+
                <License>MIT</License>
                <Authors>Jean-Philippe Bruyère</Authors>
 
@@ -17,7 +17,7 @@
                <SamplesDir>$(MSBuildThisFileDirectory)\</SamplesDir>
                <AppConfig>$(SolutionDir)Crow\App.config</AppConfig>
        </PropertyGroup>
-       
+
        <ItemGroup>
                <ProjectReference Include="$(SolutionDir)Crow\Crow.csproj" />
        </ItemGroup>
index bee992670dd0b57fef0a4aafb3b581b7c6c0cfd6..2bc30765a654cb920f9e31315634ad050c4ee9bf 100644 (file)
@@ -3,6 +3,6 @@
        <ItemGroup>
                <EmbeddedResource Include="ui\*.*">
                        <LogicalName>ShowCase.%(Filename)%(Extension)</LogicalName>
-               </EmbeddedResource>             
+               </EmbeddedResource>
        </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/Samples/ShowCase/ui/CheckBox2.imlt b/Samples/ShowCase/ui/CheckBox2.imlt
new file mode 100644 (file)
index 0000000..84ec22b
--- /dev/null
@@ -0,0 +1,7 @@
+<Label Font="{./Font}" Text="{./Caption}" Width="Stretched"
+       Margin="5"
+       Background="{./Background}"
+       Foreground="DimGrey"
+       TextAlignment="Center"
+       MouseEnter="{Foreground=White}"
+       MouseLeave="{Foreground=DimGrey}"/>
\ No newline at end of file
index ce7572ab7e83815fe5cedc7189948956bd4d1254..b37b0d8eb3f09480db70acc3e3f9f3d41e553ef2 100644 (file)
@@ -3,5 +3,6 @@
        Background = "Onyx";
 }
 CheckBox2 {
+       Template = "#ShowCase.CheckBox2.imlt";
        Width = "200";
 }
\ No newline at end of file
index 409ddd9d9472064a7f845fd296d4a7b096b366cb..de32059e9ec14251e1081a7dc7372f0c00017178 100644 (file)
@@ -3,16 +3,16 @@
        <VerticalStack  Width="25%">
                <HorizontalStack Height="Fit" Margin="2" Background="Onyx">
                        <Image Margin="2" Width="16" Height="16" Path="#Crow.Icons.level-up.svg" MouseClick="./goUpDirClick"
-                                                Background="Jet" MouseEnter="{Background=Grey}" MouseLeave="{Background=Jet}" />                       
+                                                Background="Jet" MouseEnter="{Background=Grey}" MouseLeave="{Background=Jet}" />
                        <TextBox Text="{²CurrentDir}" Margin="2"/>
-               </HorizontalStack>              
+               </HorizontalStack>
                <DirectoryView Margin="1" Name="dv" CurrentDirectory="{CurrentDir}" SelectedItemChanged="Dv_SelectedItemChanged">
                                        <Template>
                                                <TreeView IsRoot="true" Name="treeView" Data="{./FileSystemEntries}" Background="{./Background}"
                                                                SelectedItemChanged="./onSelectedItemChanged">
                                                        <ItemTemplate DataType="System.IO.FileInfo">
                                                                <ListItem CornerRadius="2" Margin="0" Height="Fit" Width="Stretched"
-                                                                               ContextCommands="{GetCommands}" 
+                                                                               ContextCommands="{GetCommands}"
                                                                                Selected="{Background=${ControlHighlight}}"
                                                                                Unselected="{Background=Transparent}">
                                                                        <HorizontalStack>
@@ -55,7 +55,7 @@
                                                                </ListItem>
                                                        </ItemTemplate>
                                                </TreeView>
-                                       </Template>             
+                                       </Template>
                                </DirectoryView>
        </VerticalStack>
        <Splitter Width="6" />
                                <Button Style="IcoButton" Command="{CMDCopy}" />
                                <Button Style="IcoButton" Command="{CMDPaste}" />-->
                                <Popper RootDataLevel="true" IsVisible="{DebugLoggingEnabled}" Fit="true">
-                                       <Template>                                      
+                                       <Template>
                                                <CheckBox IsChecked="{²./IsPopped}">
                                                        <Template>
                                                                <HorizontalStack Background="Onyx" Margin="5" Spacing="10">
                                                                        <Widget Background="Red" IsVisible="{DebugLogRecording}" CornerRadius="10" Width="12" Height="12"/>
-                                                                       <Label Text="Debug Logging" />                                                                  
+                                                                       <Label Text="Debug Logging" />
                                                                </HorizontalStack>
                                                        </Template>
                                                </CheckBox>
                                                                                        <Label Text="{../../../Caption}" Width="Stretched"/>
                                                                                        <Label Background="SeaGreen" Text="{../../../EnumValue}" Margin="3"/>
                                                                                </HorizontalStack>
-                                                                       </Template>     
-                                                                       <Wrapper Name="Content" Height="Fit" Width="{../PopWidth}" Background="Jet" />  
+                                                                       </Template>
+                                                                       <Wrapper Name="Content" Height="Fit" Width="{../PopWidth}" Background="Jet" />
                                                                </Popper>
                                                        </Template>
-                                               </EnumSelector>                                         
+                                               </EnumSelector>
                                                <EnumSelector RadioButtonStyle="CheckBox2" EnumValue="{²DiscardedEvents}" Width="Stretched" BitFieldExcludeMask="255"
                                                                        Caption="Discarded Events">
                                                        <Template>
                                                                                        <Label Text="{../../../Caption}" Width="Stretched"/>
                                                                                        <Label Background="SeaGreen" Text="{../../../EnumValue}" Margin="3"/>
                                                                                </HorizontalStack>
-                                                                       </Template>     
-                                                                       <Wrapper Name="Content" Height="Fit" Width="{../PopWidth}" Background="Jet" />  
+                                                                       </Template>
+                                                                       <Wrapper Name="Content" Height="Fit" Width="{../PopWidth}" Background="Jet" />
                                                                </Popper>
                                                        </Template>
-                                               </EnumSelector>                                         
+                                               </EnumSelector>
                                                <Label Text="Press 'F6' to start/stop recording"/>
                                        </VerticalStack>
                                </Popper>
                        </HorizontalStack>
                        <HorizontalStack>
-                               <Editor Name="tb" Text="{Source}" Multiline="true" Font="consolas, 12" Focusable="true" Height="Stretched" Width="Stretched"                                            
+                               <Editor Name="tb" Text="{Source}" Multiline="true" Font="consolas, 12" Focusable="true" Height="Stretched" Width="Stretched"
                                                TextChanged="onTextChanged" KeyDown="textView_KeyDown" ContextCommands="{EditorCommands}"
                                                Foreground="DarkGrey" Background="White" MouseWheelSpeed="20"/>
                                                <!--SelectionChanged="onSelectedTextChanged"-->
                                        </CheckBox>
                                </Template>
                                <Label Text="{ErrorMessage}" Background="DarkRed" Foreground="White" Width="Stretched" Margin="2" Multiline="true"/>
-                       </Popper>                       
+                       </Popper>
                </VerticalStack>
        </VerticalStack>
 </HorizontalStack>
index 6f78b149aadce9b7576c28b0cc9291961631e82a..fe188ebd5e9aa02ffa3a626c9621b0d4fbedf26b 100644 (file)
@@ -21,10 +21,10 @@ HStackMeasure {
        Background = "DimGrey";
 }
 CheckBox2 {
-       Template= "Interfaces/CheckBox2.imlt";
+       //Template= "Interfaces/CheckBox2.imlt";
        Background = "Jet";
        Checked="{Background=MediumSeaGreen}";
-       Unchecked = "{Background=Jet}"; 
+       Unchecked = "{Background=Jet}";
 }
 CheckBox3 {
        Template= "Interfaces/CheckBox2.imlt";
@@ -105,7 +105,7 @@ allWidgetNamedCell {
 }
 allWidgetCell2 {
        Template = "Interfaces/grpBox2.tmp";
-       Width = "20%";          
+       Width = "20%";
 }
 allWidgetHS {
        Width = "20%";
index 5b33444ad24fea241bbc294c60e3e8bd94ca0f64..fa6d1cde697da40320195d608da02e4997cf2030 100644 (file)
@@ -49,7 +49,7 @@ namespace Samples
                static void showMsgBox (object sender) {
                        Widget w = sender as Widget;
                        Command cmd = w.DataSource as Command;
-                       MessageBox.ShowModal(w.IFace, MessageBox.Type.Information, $"{cmd.Caption} CLICKED");
+                       MessageBox.ShowModal(w.IFace, MessageBox.Type.Information, $"{cmd?.Caption} CLICKED");
                }
 
                #region Test values for Binding
@@ -62,13 +62,14 @@ namespace Samples
                                new Command("Subedit command 1", (sender) => showMsgBox (sender)),
                                new Command("Subedit command 2 a bit longer", (sender) => showMsgBox (sender), null, false),
                                new Command("Subedit command three", (sender) => showMsgBox (sender))
-                       )                       
+                       )
                );
                public CommandGroup FileCommands = new CommandGroup("File Commands",
-                       new Command("File command 1", (sender) => showMsgBox (sender)),
+                       new Command("File command 1", (sender) => showMsgBox (sender), "#Icons.gavel.svg"),
                        new Command("File command 2 a bit longer", (sender) => showMsgBox (sender)),
                        new Command("File command three", (sender) => showMsgBox (sender))
                );
+               public Command SingleCommand => new Command("Single command 1", (sender) => showMsgBox (sender), "#Icons.gavel.svg");
 
                void initCommands()
                {
diff --git a/Samples/common/ui/Interfaces/Experimental/icobut.crow b/Samples/common/ui/Interfaces/Experimental/icobut.crow
new file mode 100644 (file)
index 0000000..68730dc
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<HorizontalStack Height="Fit">
+       <Button Command="{SingleCommand}" Background="DimGrey" CornerRadius="15">
+               <Template>
+                       <Border Background="{./Background}" Name="Content" Margin="8" Tooltip="{./Caption}"
+                                                                               Foreground="Transparent" CornerRadius="{../CornerRadius}" BorderWidth="1"
+                                                                               MouseEnter="{Foreground=vgradient|0:White|0.2:Grey|0.9:Grey|1:Black}"
+                                                                               MouseLeave="{Foreground=Transparent}"
+                                                                               MouseDown="{Foreground=vgradient|0:Black|0.05:Grey|0.85:Grey|1:White};{Background=${ControlHighlight}}"
+                                                                               MouseUp="{Foreground=vgradient|0:White|0.2:Grey|0.9:Grey|1:Black};{Background=DimGrey}">
+                                       <Image Name="caption" Width="32" Height="32" Path="{./Icon}" />
+                       </Border>
+               </Template>
+       </Button>
+
+       <Button Command="{SingleCommand}">
+               <Template>
+                       <Border Background="{./Background}" MinimumSize="50,20" Name="Content"
+                                                                               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}"
+                                                                               MouseDown="{Foreground=vgradient|0:Black|0.05:Grey|0.85:Grey|1:White}"
+                                                                               MouseUp="{Foreground=vgradient|0:White|0.2:Grey|0.9:Grey|1:Black}">
+                               <HorizontalStack Margin="2">
+                                       <Image Style="Icon" Path="{./Icon}"/>
+                                       <Label Font="{./Font}" Name="caption" Margin="3" Foreground="LightGrey" Text="{./Caption}"/>
+                               </HorizontalStack>
+                       </Border>
+               </Template>
+       </Button>
+</HorizontalStack>
\ No newline at end of file
diff --git a/Samples/common/ui/Interfaces/Experimental/templatedControlMargin.crow b/Samples/common/ui/Interfaces/Experimental/templatedControlMargin.crow
new file mode 100644 (file)
index 0000000..fcd4d29
--- /dev/null
@@ -0,0 +1,11 @@
+<HorizontalStack Margin="10" Height="Stretched" Visible="{ProgressVisible}" Background="SaddleBrown">
+       <ProgressBar Value="50" Maximum="100" Caption="Progress caption" Width="Stretched" Height="Stretched" Margin="0">
+               <Template>
+                       <Group Background="Red" Margin="1" Height="Stretched" Width="Stretched">
+                               <Gauge Background="DarkGrey" Foreground="RoyalBlue" Height="Stretched"
+                                               Orientation="{./Orientation}" Minimum="{./Minimum}" Maximum="{./Maximum}" Value="{./Value}"/>
+                               <Label Foreground="White" Text="{./Caption}" Width="Stretched" Margin="3" Background="Transparent" Height="Fit"/>
+                       </Group>
+               </Template>
+       </ProgressBar>
+</HorizontalStack>
\ No newline at end of file