diff options
| -rw-r--r-- | Crow/Icons/exit.svg | 6 | ||||
| -rw-r--r-- | Crow/Templates/MenuItem.itmp | 1 | ||||
| -rw-r--r-- | Crow/src/Configuration.cs | 78 | ||||
| -rw-r--r-- | Crow/src/Interface.cs | 2 | ||||
| -rw-r--r-- | Crow/src/Text/TextLineCollection.cs | 1 | ||||
| -rw-r--r-- | Crow/src/Widgets/Slider.cs | 33 | ||||
| -rw-r--r-- | Samples/PerfTests/Program.cs | 20 | ||||
| -rw-r--r-- | Samples/ShowCase/ui/showcase.crow | 15 | ||||
| -rw-r--r-- | Samples/common/src/Extensions.cs | 13 | ||||
| -rw-r--r-- | Samples/common/src/ImlParsing/Syntax.cs | 48 | ||||
| -rw-r--r-- | Samples/common/src/SampleBaseForEditor.cs | 7 | ||||
| -rw-r--r-- | Samples/common/ui/Interfaces/menuItem.itmp | 2 |
12 files changed, 139 insertions, 87 deletions
diff --git a/Crow/Icons/exit.svg b/Crow/Icons/exit.svg index cb8d1c27..e5944ee2 100644 --- a/Crow/Icons/exit.svg +++ b/Crow/Icons/exit.svg @@ -8,12 +8,8 @@ <path style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:9;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="m 13.884262,15.143117 c 24.231966,13.49131 34.18672,34.186719 34.18672,34.186719" - id="path4175" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> + id="path4175"/> <path - sodipodi:nodetypes="cc" - inkscape:connector-curvature="0" id="path4177" d="M 50.43178,15.408178 C 20.436536,37.282439 16.245061,49.594898 16.245061,49.594898" style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:9;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> diff --git a/Crow/Templates/MenuItem.itmp b/Crow/Templates/MenuItem.itmp index b1d062ab..19136fcc 100644 --- a/Crow/Templates/MenuItem.itmp +++ b/Crow/Templates/MenuItem.itmp @@ -2,7 +2,6 @@ <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> diff --git a/Crow/src/Configuration.cs b/Crow/src/Configuration.cs index f3dadd18..28a5293a 100644 --- a/Crow/src/Configuration.cs +++ b/Crow/src/Configuration.cs @@ -46,12 +46,12 @@ namespace Crow } /// <summary> /// Application wide Configuration store utility - /// - /// configuration files are automatically stored in **_user/.config/appname/app.config_** on close and every minutes - /// if some items have changed. + /// + /// configuration files are automatically stored in **_user/.config/appname/appname.config_** on close and at interval defined by + /// the static field `Configuration.AUTO_SAVE_INTERVAL` but only if some items have changed. /// New items are automaticaly added on first use. Configuration class expose one templated Get and one Templated Set, so /// creating, storing and retrieving config items is simple as: - /// + /// /// ```csharp\n /// //storing\n /// Configuration.Global.Set ("Option1", 42);\n @@ -59,39 +59,61 @@ namespace Crow /// int op1 = Configuration.Global.Get<int> ("Option1");\n /// ```\n /// </summary> - /// + /// /// **.config** file are simple text files with per line, a key/value pair of the form `option=value`. Keys have to be unique /// in the application scope. - /// + /// /// When running the application for the first time, some default options may be necessary. Their can be defined /// in a special embedded resource text file with the key '**appname.default.config**' + /// + /// You may also provide a default value when you fetch an item: + /// ```csharp\n + /// int op1 = Configuration.Global.Get<int> ("Option1", 10);\n + /// ```\n + /// public class Configuration { volatile bool isDirty = false; string configPath; Dictionary<string, ConfigItem> items = new Dictionary<string, ConfigItem> (); static Configuration globalConfig; - - public static Configuration Global { get { return globalConfig; } } - + /// <summary> + /// Interval in milliseconds between configuration file saving. Save is done only if an item has changed. + /// Default value is 200. + /// </summary> + public static int AUTO_SAVE_INTERVAL = 200; + /// <summary> + /// Default application wide store for configuration items. It's created and updated automaticaly when needed. + /// It's path is: **_user/.config/appname/appname.config_**. + /// </summary> + public static Configuration Global => globalConfig; + /// <summary> + /// Create a custom configuration store with the provided path. + /// </summary> + /// <param name="path">the full path where to save this configuration store.</param> + /// <param name="defaultConf">an optional text stream with default values.</param> public Configuration (string path, Stream defaultConf = null) { configPath = path; if (File.Exists (configPath)) { using (Stream s = new FileStream (configPath, FileMode.Open)) load (s); - - } else if (defaultConf != null) { + + } else if (defaultConf != null) { load (defaultConf); } startSavingThread (); } /// <summary> - /// Create readonly configuration + /// Create a readonly configuration /// </summary> /// <param name="defaultConf"></param> - public Configuration (Stream defaultConf = null) { + public Configuration (Stream defaultConf = null) { load (defaultConf); } + /// <summary> + /// Get the application configuration directory full path. + /// </summary> + /// <returns>application configuration directory full path</returns> public static string AppConfigPath => Path.Combine ( Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.UserProfile), ".config") , Assembly.GetEntryAssembly ().GetName().Name); @@ -121,6 +143,10 @@ namespace Crow globalConfig = new Configuration (globalConfigPath); } + /// <summary> + /// Get all the configuration item names currently present in this configuration store. + /// </summary> + /// <value>configuration item names</value> public string[] Names { get { return items.Keys.ToArray (); @@ -139,6 +165,13 @@ namespace Crow Thread.Sleep (100); } } + /// <summary> + /// Try to fetch a configuration item by name. + /// </summary> + /// <param name="key">the configuration item name</param> + /// <param name="result">the current value, or the type default if not found in store.</param> + /// <typeparam name="T">The type of the configuration item</typeparam> + /// <returns>true if the item was present, false otherwise</returns> public bool TryGet<T> (string key, out T result) { if (items.ContainsKey (key)){ result = items [key].GetValue<T> (); @@ -148,21 +181,27 @@ namespace Crow return false; } /// <summary> - /// retrive the value of the configuration key given in parameter + /// Retrieve an item from this configuration store identified by the key given in parameter /// </summary> - /// <param name="key">option name</param> + /// <param name="key">configuration item name</param> + /// <typeparam name="T">the type of the configuration item</typeparam> + /// <returns>The current value or the default one if not yet defined.</returns> public T Get<T>(string key) { return !items.ContainsKey (key) ? default(T) : items [key].GetValue<T> (); } /// <summary> - /// retrive the value of the configuration key given in parameter + /// Retrieve an item from this configuration store identified by the key given in parameter, or + /// return the default value provided as parameter. /// </summary> - /// <param name="key">option name</param> + /// <param name="key">configuration item name</param> + /// <param name="defaultValue">a default value in case this item is not yet present in the configuration store</param> + /// <typeparam name="T">the type of the configuration item</typeparam> + /// <returns>The current value or the default one if not yet defined.</returns> public T Get<T>(string key, T defaultValue) { return !items.ContainsKey (key) ? defaultValue : items [key].GetValue<T> (); - } + } /// <summary> /// store the value of the configuration key given in parameter /// </summary> @@ -177,6 +216,9 @@ namespace Crow items[key].Set (value); isDirty = true; } + /// <summary> + /// Save this configuration store with the path provided on creation. This is done automaticaly normaly. + /// </summary> public void Save(){ using (Stream s = new FileStream(configPath,FileMode.Create)){ using (StreamWriter sw = new StreamWriter (s)) { diff --git a/Crow/src/Interface.cs b/Crow/src/Interface.cs index 66aa0e69..d3dd99f4 100644 --- a/Crow/src/Interface.cs +++ b/Crow/src/Interface.cs @@ -85,8 +85,6 @@ namespace Crow { case "cairo": return NativeLibrary.Load("cairo-2", assembly, null); - /*case "glfw3": - return NativeLibrary.Load("glfw", assembly, null);*/ case "rsvg-2.40": return NativeLibrary.Load("rsvg-2", assembly, null); } diff --git a/Crow/src/Text/TextLineCollection.cs b/Crow/src/Text/TextLineCollection.cs index 19be9c9e..ba40e084 100644 --- a/Crow/src/Text/TextLineCollection.cs +++ b/Crow/src/Text/TextLineCollection.cs @@ -124,6 +124,7 @@ namespace Crow.Text } return new CharLocation (result, absolutePosition - lines[result].Start); } + [Obsolete] public void UpdateLineLengthInPixel (int index, int lengthInPixel) { lines[index].LengthInPixel = lengthInPixel; } diff --git a/Crow/src/Widgets/Slider.cs b/Crow/src/Widgets/Slider.cs index e1e8d90e..8d6615a7 100644 --- a/Crow/src/Widgets/Slider.cs +++ b/Crow/src/Widgets/Slider.cs @@ -19,14 +19,21 @@ namespace Crow #endregion #region implemented abstract members of TemplatedControl + Widget cursorParent; protected override void loadTemplate (Widget template = null) { + if (cursorParent != null) { + cursorParent.LayoutChanged -= HandleCursorContainerLayoutChanged; + cursorParent = null; + } base.loadTemplate (template); cursor = child.FindByName ("Cursor"); if (cursor == null) return; - (cursor.Parent as Widget).LayoutChanged += HandleCursorContainerLayoutChanged;//too difficult to unregister + cursorParent = cursor.Parent as Widget; + cursorParent.LayoutChanged += HandleCursorContainerLayoutChanged; + updateCursorWidgetProps (); } @@ -36,9 +43,6 @@ namespace Crow } #endregion - - - protected override void registerUpdate () => RegisterForLayouting (LayoutingType.ArrangeChildren); @@ -221,20 +225,33 @@ namespace Crow base.onMouseMove (sender, e); } #endregion - - public void OnDecrease (object sender, MouseButtonEventArgs e) + /// <summary> + /// Handler to decrease current value by `SmallIncrement` + /// </summary> + /// <param name="sender">event sender</param> + /// <param name="e">event argument</param> + public void OnDecrease (object sender, EventArgs e) { Value -= SmallIncrement; } - public void OnIncrease (object sender, MouseButtonEventArgs e) + /// <summary> + /// Handler to increase current value by `SmallIncrement` + /// </summary> + /// <param name="sender">event sender</param> + /// <param name="e">event argument</param> + public void OnIncrease (object sender, EventArgs e) { Value += SmallIncrement; } protected override void Dispose(bool disposing) { - base.Dispose(disposing); + if (cursorParent != null) { + cursorParent.LayoutChanged -= HandleCursorContainerLayoutChanged; + cursorParent = null; + } + base.Dispose(disposing); } } } diff --git a/Samples/PerfTests/Program.cs b/Samples/PerfTests/Program.cs index 222b7e7a..d7f6a9be 100644 --- a/Samples/PerfTests/Program.cs +++ b/Samples/PerfTests/Program.cs @@ -14,26 +14,6 @@ namespace PerfTests { class TestInterface : Interface { -#if NETCOREAPP - static IntPtr resolveUnmanaged (Assembly assembly, String libraryName) { - - switch (libraryName) - { - case "cairo": - return NativeLibrary.Load("cairo-2", assembly, null); - case "glfw3": - return NativeLibrary.Load("glfw", assembly, null); - case "rsvg-2.40": - return NativeLibrary.Load("rsvg-2", assembly, null); - } - Console.WriteLine ($"[UNRESOLVE] {assembly} {libraryName}"); - return IntPtr.Zero; - } - - static TestInterface () { - System.Runtime.Loader.AssemblyLoadContext.Default.ResolvingUnmanagedDll+=resolveUnmanaged; - } -#endif readonly int count = 10, updateCycles = 0; readonly bool screenOutput = false; readonly string inDirectory = null;//directory to test diff --git a/Samples/ShowCase/ui/showcase.crow b/Samples/ShowCase/ui/showcase.crow index c5b683da..62b676df 100644 --- a/Samples/ShowCase/ui/showcase.crow +++ b/Samples/ShowCase/ui/showcase.crow @@ -76,8 +76,17 @@ </VerticalStack>--> <Container Name="CrowContainer" Height="60%" Background="Black"/> <Splitter/> + <Menu Data="{EditorAllCommands}" Height="Fit" Width="Stretched"> + <ItemTemplate DataType="Crow.Command" Path="Interfaces/menuCommand.itmp"/> + <ItemTemplate DataType="Crow.CommandGroup" > + <MenuItem Data="{Commands}" Width="Fit" IsEnabled="{CanExecute}" + Template="Interfaces/menuItem.template" + ItemTemplate="Interfaces/menuItem.itmp"> + </MenuItem> + </ItemTemplate> + </Menu> <VerticalStack CacheEnabled="true"> - <Wrapper Orientation="Vertical" Height="Fit"> + <!-- <Wrapper Orientation="Vertical" Height="Fit"> <Button Style="IcoButton" Command="{CMDNew}" /> <Button Style="IcoButton" Command="{CMDSave}" /> <Button Style="IcoButton" Command="{CMDSaveAs}" /> @@ -151,10 +160,10 @@ Tooltip="Add '*source* where you want to load the source in the editor."/> </VerticalStack> </Popper> - </Wrapper> + </Wrapper>--> <HorizontalStack> <Editor Name="tb" Text="{Source}" Multiline="true" Font="consolas, 12" Focusable="true" Height="Stretched" Width="Stretched" - TextChanged="onTextChanged" KeyDown="textView_KeyDown" ContextCommands="{EditorCommands}" + TextChanged="onTextChanged" KeyDown="textView_KeyDown" ContextCommands="{EditorEditCommands}" SelectionChanged="onEditorSelectionChanged" Foreground="DarkGrey" Background="White" MouseWheelSpeed="20"/> <ScrollBar Value="{²../tb.ScrollY}" diff --git a/Samples/common/src/Extensions.cs b/Samples/common/src/Extensions.cs index 7647dbc9..02433011 100644 --- a/Samples/common/src/Extensions.cs +++ b/Samples/common/src/Extensions.cs @@ -1,20 +1,25 @@ +using System.IO; using System.Reflection; using Crow; namespace Samples { public static class Extensions { - public static CommandGroup GetCommands (this System.IO.DirectoryInfo di) => + public static CommandGroup GetCommands (this DirectoryInfo di) => new CommandGroup( - new ActionCommand ("Set as root", ()=> {SampleBaseForEditor.CurrentProgramInstance.CurrentDir = di.FullName;}) + new ActionCommand ("Set as root", ()=> {SampleBaseForEditor.CurrentProgramInstance.CurrentDir = di.FullName;})/*, + new ActionCommand ("New Directory", (sender0) => { + Directory.CreateDirectory (Path.Combine (di.FullName, "new directory")); + Widget listContainer = ((sender0 as Widget).LogicalParent as Widget).DataSource as Widget; + })*/ ); - public static CommandGroup GetCommands (this System.IO.FileInfo fi) => + public static CommandGroup GetCommands (this FileInfo fi) => new CommandGroup( new ActionCommand ("Delete", (sender0) => { MessageBox.ShowModal (SampleBaseForEditor.CurrentProgramInstance, MessageBox.Type.YesNo, $"Delete {fi.Name}?").Yes += (sender, e) => { - System.IO.File.Delete(fi.FullName); + File.Delete(fi.FullName); Widget listContainer = ((sender0 as Widget).LogicalParent as Widget).DataSource as Widget; (listContainer.Parent as Group).RemoveChild(listContainer); }; diff --git a/Samples/common/src/ImlParsing/Syntax.cs b/Samples/common/src/ImlParsing/Syntax.cs index 92c9eec3..ddbc6a92 100644 --- a/Samples/common/src/ImlParsing/Syntax.cs +++ b/Samples/common/src/ImlParsing/Syntax.cs @@ -8,13 +8,13 @@ using System.Linq; namespace Crow { public class SyntaxException : Exception { - public readonly Token Token; + public readonly Token Token; public SyntaxException(string message, Token token = default, Exception innerException = null) : base (message, innerException) { Token = token; } } - public class SyntaxAnalyser { + public class SyntaxAnalyser { XmlSource source; IEnumerable<Token> tokens => source.Tokens; public SyntaxNode Root => CurrentNode; @@ -44,7 +44,7 @@ namespace Crow throw new SyntaxException ("Unexpected end of source"); } - Token accept (IEnumerator<Token> iter, TokenType acceptedTokenType) { + Token accept (IEnumerator<Token> iter, TokenType acceptedTokenType) { if (iter.Current.Type == acceptedTokenType) return iter.Current; else @@ -58,7 +58,7 @@ namespace Crow Token eltOpen = iter.Current; moveNextOrThrow (iter); Token eltName = accept (iter, TokenType.ElementName); - + List<SyntaxNode> attributes = readAttributes (iter); if (iter.Current.Type == TokenType.EmptyElementClosing || iter.Current.Type == TokenType.ClosingSign) @@ -70,7 +70,7 @@ namespace Crow Token eltOpen = iter.Current; moveNextOrThrow (iter); Token eltName = accept (iter, TokenType.ElementName); - moveNextOrThrow (iter); + moveNextOrThrow (iter); return new ElementEndTagSyntax(source, eltOpen, eltName, accept (iter, TokenType.ClosingSign)); }*/ @@ -87,7 +87,7 @@ namespace Crow Exceptions = new List<SyntaxException> (); CurrentNode = new IMLRootSyntax (source); previousTok = default; - iter = tokens.GetEnumerator (); + iter = tokens.GetEnumerator (); bool notEndOfSource = iter.MoveNext (); while (notEndOfSource) { @@ -100,7 +100,7 @@ namespace Crow } else if (iter.Current.Type == TokenType.ElementName) tag.NameToken = iter.Current; else if (iter.Current.Type == TokenType.ClosingSign) { - tag.EndToken = iter.Current; + tag.EndToken = iter.Current; CurrentNode = tag.Parent; CurrentNode.RemoveChild (tag); CurrentNode = CurrentNode.AddChild (new ElementSyntax (tag)); @@ -113,13 +113,13 @@ namespace Crow Exceptions.Add (new SyntaxException ("Unexpected Token", iter.Current)); CurrentNode.EndToken = previousTok; CurrentNode = CurrentNode.Parent; - continue; + continue; } } else if (CurrentNode is ElementSyntax elt) { if (iter.Current.Type == TokenType.ElementOpen) CurrentNode = CurrentNode.AddChild (new ElementStartTagSyntax (iter.Current)); - else if (iter.Current.Type == TokenType.EndElementOpen) { - elt.EndTag = new ElementEndTagSyntax (iter.Current); + else if (iter.Current.Type == TokenType.EndElementOpen) { + elt.EndTag = new ElementEndTagSyntax (iter.Current); CurrentNode = elt.AddChild (elt.EndTag); } } else if (CurrentNode is AttributeSyntax attrib) { @@ -139,7 +139,7 @@ namespace Crow Exceptions.Add (new SyntaxException ("Unexpected Token", iter.Current)); CurrentNode.EndToken = previousTok; CurrentNode = CurrentNode.Parent; - continue; + continue; } } else if (CurrentNode is ElementEndTagSyntax eltEndTag) { if (iter.Current.Type == TokenType.ElementName) @@ -151,7 +151,7 @@ namespace Crow Exceptions.Add (new SyntaxException ("Unexpected Token", iter.Current)); eltEndTag.EndToken = eltEndTag.Parent.EndToken = previousTok; CurrentNode = CurrentNode.Parent.Parent; - continue; + continue; } } else if (CurrentNode is IMLRootSyntax) { switch (iter.Current.Type) { @@ -179,11 +179,11 @@ namespace Crow Exceptions.Add (new SyntaxException ("Unexpected Token", iter.Current)); pi.EndToken = previousTok; CurrentNode = CurrentNode.Parent; - continue; + continue; } } } - + previousTok = iter.Current; notEndOfSource = iter.MoveNext (); } @@ -191,16 +191,16 @@ namespace Crow if (!CurrentNode.EndToken.HasValue) CurrentNode.EndToken = previousTok; CurrentNode = CurrentNode.Parent; - } + } } } public class SyntaxNode { public SyntaxNode Parent { get; private set; } List<SyntaxNode> children = new List<SyntaxNode> (); - + public readonly Token StartToken; public Token? EndToken { get; internal set; } - public SyntaxNode (Token tokStart, Token? tokEnd = null) { + public SyntaxNode (Token tokStart, Token? tokEnd = null) { StartToken = tokStart; EndToken = tokEnd; } @@ -271,7 +271,7 @@ namespace Crow protected ElementTagSyntax (Token startTok) : base (startTok) { } - } + } public class ElementStartTagSyntax : ElementTagSyntax { public ElementStartTagSyntax (Token startTok) : base (startTok) { @@ -282,11 +282,11 @@ namespace Crow : base (startTok) { } } - + public class EmptyElementSyntax : SyntaxNode { public readonly ElementStartTagSyntax StartTag; public EmptyElementSyntax (ElementStartTagSyntax startNode) : base (startNode.StartToken, startNode.EndToken) { - StartTag = startNode; + StartTag = startNode; AddChild (StartTag); } } @@ -298,7 +298,7 @@ namespace Crow public override bool IsComplete => base.IsComplete & StartTag.IsComplete & (EndTag != null && EndTag.IsComplete); public ElementSyntax (ElementStartTagSyntax startTag) - : base (startTag.StartToken) { + : base (startTag.StartToken) { StartTag = startTag; AddChild (StartTag); } @@ -307,9 +307,9 @@ namespace Crow public class AttributeSyntax : SyntaxNode { public Token? NameToken { get; internal set; } public Token? EqualToken { get; internal set; } - public Token? ValueOpenToken { get; internal set; } - public Token? ValueCloseToken { get; internal set; } - public Token? ValueToken { get; internal set; } + public Token? ValueOpenToken { get; internal set; } + public Token? ValueCloseToken { get; internal set; } + public Token? ValueToken { get; internal set; } public AttributeSyntax (Token startTok) : base (startTok) {} public override bool IsComplete => base.IsComplete & NameToken.HasValue & EqualToken.HasValue & ValueToken.HasValue & ValueOpenToken.HasValue & ValueCloseToken.HasValue; } diff --git a/Samples/common/src/SampleBaseForEditor.cs b/Samples/common/src/SampleBaseForEditor.cs index b207eea3..5c87226d 100644 --- a/Samples/common/src/SampleBaseForEditor.cs +++ b/Samples/common/src/SampleBaseForEditor.cs @@ -127,7 +127,7 @@ namespace Samples public ActionCommand CMDNew, CMDOpen, CMDSave, CMDSaveAs, CMDQuit, CMDShowLeftPane, CMDUndo, CMDRedo, CMDCut, CMDCopy, CMDPaste, CMDHelp, CMDAbout, CMDOptions; - public CommandGroup EditorCommands => new CommandGroup (CMDUndo, CMDRedo, CMDCut, CMDCopy, CMDPaste, CMDSave, CMDSaveAs); + public CommandGroup EditorFileCommands, EditorEditCommands, EditorAllCommands; protected virtual void initCommands () { CMDNew = new ActionCommand ("New", new Action (onNewFile), "#Icons.blank-file.svg"); @@ -139,6 +139,11 @@ namespace Samples CMDCut = new ActionCommand ("Cut", new Action (cut), "#Icons.scissors.svg", false); CMDCopy = new ActionCommand ("Copy", new Action (copy), "#Icons.copy-file.svg", false); CMDPaste= new ActionCommand ("Paste", new Action (paste), "#Icons.paste-on-document.svg", false); + + EditorFileCommands = new CommandGroup ("File", CMDSave, CMDSaveAs, CMDQuit); + EditorEditCommands = new CommandGroup ("Edit", CMDUndo, CMDRedo, CMDCut, CMDCopy, CMDPaste); + + EditorAllCommands = new CommandGroup (EditorFileCommands, EditorEditCommands); } diff --git a/Samples/common/ui/Interfaces/menuItem.itmp b/Samples/common/ui/Interfaces/menuItem.itmp index 04bc10a6..a129769a 100644 --- a/Samples/common/ui/Interfaces/menuItem.itmp +++ b/Samples/common/ui/Interfaces/menuItem.itmp @@ -7,7 +7,7 @@ <Template> <Label Text="{./Caption}" Width="Stretched" Height="Stretched" Margin="3" Background="{./Background}"/> - </Template> + </Template> <VerticalStack Margin="0" Name="ItemsContainer" Fit="true" Background="Jet"/> </Popper> </ItemTemplate> |