From: Jean-Philippe Bruyère Date: Mon, 1 Jun 2020 23:18:31 +0000 (+0200) Subject: styling constants X-Git-Tag: v0.9.5-beta~113^2~23 X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=d137c0e74445b540bcdafc7a9e04463b4199c076;p=jp%2Fcrow.git styling constants --- diff --git a/Crow.sln b/Crow.sln index 159a127b..df52304f 100644 --- a/Crow.sln +++ b/Crow.sln @@ -11,6 +11,9 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Crow", "Crow\Crow.csproj", "{C2980F9B-4798-4C05-99E2-E174810F7C7B}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{B2C7855A-2878-47FD-AD32-9A83DB4AB8C6}" + ProjectSection(SolutionItems) = preProject + Samples\Directory.Build.props = Samples\Directory.Build.props + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HelloWorld", "Samples\HelloWorld\HelloWorld.csproj", "{F535A8AB-CD93-49AB-B1B0-FFF9AE51ED6A}" EndProject diff --git a/Crow/Default.style b/Crow/Default.style index 6264dafe..8c443443 100644 --- a/Crow/Default.style +++ b/Crow/Default.style @@ -1,4 +1,6 @@ -Button, CheckBox, RadioButton, ComboBox, Expandable, +ControlBackground = "Transparent"; + +Button, CheckBox, RadioButton, ComboBox, Expandable, MessageBox, Popper, Slider, Spinner, TextBox { Focusable = "true"; Height = "Fit"; @@ -19,7 +21,7 @@ Control { ControlBorder { BorderWidth = "1"; Foreground = "DimGrey"; - Background = "Transparent"; + Background = "${ControlBackground}"; CornerRadius = "0"; } ControlCaption { diff --git a/Crow/src/Interface.cs b/Crow/src/Interface.cs index f97eb8e1..721404d2 100644 --- a/Crow/src/Interface.cs +++ b/Crow/src/Interface.cs @@ -435,6 +435,16 @@ namespace Crow public Dictionary DefaultValuesLoader = new Dictionary(); /// Store dictionnary of member/value per StyleKey public Dictionary Styling; + /// + /// Replacement value for style like cmake or bash variable. + /// + /// + /// each 'key=value' pair in style files not enclosed in brackets are threated as constant. + /// If the same constant is defined more than once, only the first is kept. + /// Than in any IML expresion, in style or xml, constant may be used as a replacement string with ${CONSTANTID}. + /// If a constant is not resolved in iml while creating the instantiator, an error is thrown. + /// + public readonly Dictionary StylingConstants = new Dictionary (); /// parse all styling data's during application startup and build global Styling Dictionary protected virtual void loadStyling() { Styling = new Dictionary (); @@ -451,9 +461,8 @@ namespace Crow foreach (string s in assembly .GetManifestResourceNames () .Where (r => r.EndsWith (".style", StringComparison.OrdinalIgnoreCase))) { - using (Stream stream = assembly.GetManifestResourceStream (s)) { - new StyleReader (this.Styling, stream, s); - } + using (StyleReader sr = new StyleReader (assembly.GetManifestResourceStream (s))) + sr.Parse (this, s); } } #endregion diff --git a/Crow/src/styling/StyleReader.cs b/Crow/src/styling/StyleReader.cs index 77b8967d..cace196a 100644 --- a/Crow/src/styling/StyleReader.cs +++ b/Crow/src/styling/StyleReader.cs @@ -17,12 +17,10 @@ namespace Crow //TODO: style key shared by different class may use only first encouneter class setter, which can cause bug. public class StyleReader : StreamReader { - enum States { init, classNames, members, value, endOfStatement } + enum States { classNames, members, value, endOfStatement } - States curState = States.init; + States curState = States.classNames; - int column = 1; - int line = 1; #region Character ValidityCheck static Regex rxValidChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}"); @@ -31,13 +29,11 @@ namespace Crow static Regex rxDecimal = new Regex(@"[0-9]+"); static Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+"); - public bool nextCharIsValidCharStartName - { - get { return rxNameStartChar.IsMatch(new string(new char[]{PeekChar()})); } + bool nextCharIsValidCharStartName { + get => rxNameStartChar.IsMatch(new string(new char[]{PeekChar()})); } - public bool nextCharIsValidCharName - { - get { return rxNameChar.IsMatch(new string(new char[]{PeekChar()})); } + bool nextCharIsValidCharName { + get => rxNameChar.IsMatch(new string(new char[]{PeekChar()})); } #endregion @@ -59,9 +55,17 @@ namespace Crow } } - public StyleReader (Dictionary styling, Stream stream, string resId) - : base(stream) - { + /// + /// Parse the full style stream and load the result in 'Styling' and 'StylingConstant' + /// fields of the interface passed as argument. + /// + /// the Interface to load the style for + public void Parse (Interface iFace, string resId) + { + int column = 1; + int line = 1; + curState = States.classNames; + string styleKey = resId.Substring (0, resId.Length - 6); string token = ""; List targetsClasses = new List (); @@ -72,7 +76,7 @@ namespace Crow if (EndOfStream) break; - switch (Peek()) { + switch (Peek ()) { case '/': ReadChar (); if (PeekChar () != '/') @@ -81,7 +85,7 @@ namespace Crow break; case ',': ReadChar (); - if (!(curState == States.init || curState == States.classNames) || string.IsNullOrEmpty (token)) + if (!(curState == States.classNames) || string.IsNullOrEmpty (token)) throw new ParserException (line, column, "Unexpected char ','", resId); targetsClasses.Add (token); token = ""; @@ -89,7 +93,7 @@ namespace Crow break; case '{': ReadChar (); - if (!(curState == States.init || curState == States.classNames) || string.IsNullOrEmpty (token)) + if (curState != States.classNames || string.IsNullOrEmpty (token)) throw new ParserException (line, column, "Unexpected char '{'", resId); targetsClasses.Add (token); token = ""; @@ -104,7 +108,7 @@ namespace Crow break; case '=': ReadChar (); - if (!(curState == States.init || curState == States.members)) + if (!(curState == States.members || curState == States.classNames) || string.IsNullOrEmpty (token)) throw new ParserException (line, column, "Unexpected char '='", resId); currentProperty = token; token = ""; @@ -112,38 +116,59 @@ namespace Crow break; case '"': if (curState != States.value) - throw new ParserException (line, column, "Unexpected char '\"'", resId); + throw new ParserException (line, column, "Unexpected char '\"'", resId); ReadChar (); while (!EndOfStream) { - char c = PeekChar(); - if (c == '\"') { - ReadChar (); + char c = ReadChar (); + if (c == '$') { + if (PeekChar () == '{') { + ReadChar (); + //constant replacement + string constantId = ""; + while (!EndOfStream) { + c = ReadChar (); + if (c == '}') + break; + constantId += c; + } + if (string.IsNullOrEmpty (constantId) || !iFace.StylingConstants.ContainsKey (constantId)) + throw new ParserException (line, column, "Empty constant id in styling", resId); + token += iFace.StylingConstants [constantId]; + continue; + } + } else if (c == '\"') { + curState = States.endOfStatement; break; } - token += ReadChar(); - if (c == '\\' && !EndOfStream) - token += ReadChar(); + token += c; } - curState = States.endOfStatement; break; case ';': if (curState != States.endOfStatement) - throw new ParserException (line, column, "Unexpected end of statement", resId); + throw new ParserException (line, column, "Unexpected end of statement", resId); ReadChar (); - foreach (string tc in targetsClasses) { - if (!styling.ContainsKey (tc)) - styling [tc] = new Style (); - else if (styling [tc].ContainsKey (currentProperty)) - continue; - styling [tc] [currentProperty] = token; - #if DESIGN_MODE + if (targetsClasses.Count == 0) { + //style constant + if (!iFace.StylingConstants.ContainsKey (currentProperty)) + iFace.StylingConstants.Add (currentProperty, token); + curState = States.classNames; + } else { + foreach (string tc in targetsClasses) { + if (!iFace.Styling.ContainsKey (tc)) + iFace.Styling [tc] = new Style (); + else if (iFace.Styling [tc].ContainsKey (currentProperty)) + continue; + iFace.Styling [tc] [currentProperty] = token; +#if DESIGN_MODE styling [tc].Locations[currentProperty] = new FileLocation(resId, line, column - token.Length - 1, token.Length); - #endif - //System.Diagnostics.Debug.WriteLine ("Style: {3} : {0}.{1} = {2}", tc, currentProperty, token, resId); +#endif + //System.Diagnostics.Debug.WriteLine ("Style: {3} : {0}.{1} = {2}", tc, currentProperty, token, resId); + } + curState = States.members; } token = ""; - curState = States.members; + currentProperty = ""; break; default: if (curState == States.value) @@ -152,13 +177,19 @@ namespace Crow throw new ParserException (line, column, "expecting end of statement", resId); if (nextCharIsValidCharStartName) { - token += ReadChar(); + token += ReadChar (); while (nextCharIsValidCharName) - token += ReadChar(); + token += ReadChar (); } break; } } + + } + + public StyleReader (Stream stream) + : base(stream) + { } } } diff --git a/Samples/BasicTests/BasicTests.cs b/Samples/BasicTests/BasicTests.cs index fba4b70a..1a9340d5 100644 --- a/Samples/BasicTests/BasicTests.cs +++ b/Samples/BasicTests/BasicTests.cs @@ -15,6 +15,7 @@ namespace tests #if NETCOREAPP3_1 DllMapCore.Resolve.Enable (true); #endif + using (BasicTests app = new BasicTests ()) { app.Run (); } @@ -98,8 +99,11 @@ namespace tests else if (idx < 0) idx = testFiles.Length - 1; +#if NETCOREAPP3_1 Console.WriteLine ($"Loading {testFiles [idx]}. {AppDomain.CurrentDomain.MonitoringSurvivedMemorySize}"); - +#else + Console.WriteLine ($"Loading {testFiles [idx]}. {GC.GetTotalMemory(true)}"); +#endif Load (testFiles [idx]).DataSource = this; } catch (Exception ex) { (LoadIMLFragment ($"