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> ();
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
//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}");
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
}
}
- 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> ();
if (EndOfStream)
break;
- switch (Peek()) {
+ switch (Peek ()) {
case '/':
ReadChar ();
if (PeekChar () != '/')
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 = "";
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 = "";
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 = "";
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)
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)
+ {
}
}
}