]> O.S.I.I.S - jp/crow.git/commitdiff
styling constants
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Mon, 1 Jun 2020 23:18:31 +0000 (01:18 +0200)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Mon, 1 Jun 2020 23:18:31 +0000 (01:18 +0200)
Crow.sln
Crow/Default.style
Crow/src/Interface.cs
Crow/src/styling/StyleReader.cs
Samples/BasicTests/BasicTests.cs
Samples/common/SampleBase.cs

index 159a127b7fe11cb54506d3296c65651eab357c7a..df52304f167f624237f145595774de659291d3c7 100644 (file)
--- 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
index 6264dafeafa1831dd448853f7c90ee799a344049..8c4434436f736a0451fc69b8724623adeb2b286d 100644 (file)
@@ -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 {
index f97eb8e17ba6d24f8739a9793fa19ec118760bc8..721404d22f60fba5b317d2e6157c0db392c5d27b 100644 (file)
@@ -435,6 +435,16 @@ namespace Crow
                public Dictionary<String, LoaderInvoker> DefaultValuesLoader = new Dictionary<string, LoaderInvoker>();
                /// <summary>Store dictionnary of member/value per StyleKey</summary>
                public Dictionary<string, Style> Styling;
+               /// <summary>
+               /// Replacement value for style like cmake or bash variable.
+               /// </summary>
+               /// <remarks>
+               /// 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.
+               /// </remarks>
+               public readonly Dictionary<string, string> StylingConstants = new Dictionary<string, string> ();
                /// <summary> parse all styling data's during application startup and build global Styling Dictionary </summary>
                protected virtual void loadStyling() {
                        Styling = new Dictionary<string, Style> ();
@@ -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
index 77b8967d3697b53fd949d8cca1261cd804eb8d4e..cace196a81c26e28190eb93bf907e5bb5a596ab0 100644 (file)
@@ -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<string, Style> styling, Stream stream, string resId)
-                       : base(stream)
-               {                       
+               /// <summary>
+               /// Parse the full style stream and load the result in 'Styling' and 'StylingConstant'
+               /// fields of the interface passed as argument.
+               /// </summary>
+               /// <param name="iFace">the Interface to load the style for</param>
+               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<string> targetsClasses = new List<string> ();
@@ -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)
+               {
                }
        }
 }
index fba4b70ad1ebad65258f4f82961ba11854e127e9..1a9340d5c087afd9275a20fa1f8cca47fb809dc1 100644 (file)
@@ -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 ($"<Label Background='Red' Foreground='White' Height='Fit' Width='Stretched' Multiline='true' VerticalAlignment='Bottom' Margin='5' />") as Label).Text = ex.ToString();
index 6800e9eff883280832eca47c4bc6b1c5ba76cb62..0007fc23b8e5bb0fd53b79888932fc46dc78a88f 100644 (file)
@@ -12,7 +12,7 @@ namespace Crow
                public Version CrowVersion => Assembly.GetAssembly (typeof (Widget)).GetName ().Version;
 
                #region Test values for Binding
-               public List<Crow.Command> Commands;
+               public List<Command> Commands;
                public int intValue = 500;
                VerticalAlignment currentVAlign;