Button, CheckBox, RadioButton, ComboBox, Expandable,
MessageBox, Popper, Slider, Spinner, TextBox {
- Focusable = true;
- Height = Fit;
+ Focusable = "true";
+ Height = "Fit";
}
Border {
- Foreground = Gray;
+ Foreground = "Gray";
}
-CheckBox { Caption = CheckBox; }
-RadioButton { Caption = RadioButton; }
-Expandable { Caption = Expandable; }
-Popper { Caption = Popper;}
-GroupBox { Caption = Group Box; }
+CheckBox { Caption = "CheckBox"; }
+RadioButton { Caption = "RadioButton"; }
+Expandable { Caption = "Expandable"; }
+Popper { Caption = "Popper";}
+GroupBox { Caption = "Group Box"; }
ControlBorder {
- BorderWidth = 1;
- Foreground = Jet;
- Background = Transparent;
+ BorderWidth = "1";
+ Foreground = "Jet";
+ Background = "Transparent";
}
ControlCaption {
- Foreground = Gray;
- MouseEnter = {Foreground=White};
- MouseLeave = {Foreground=Gray};
+ Foreground = "Gray";
+ MouseEnter = "{Foreground=White}";
+ MouseLeave = "{Foreground=Gray}";
}
Icon {
- Margin=1;
- Width=12;
- Height=12;
+ Margin = "1";
+ Width = "12";
+ Height = "12";
}
Wrapper {
- Orientation = Vertical;
+ Orientation = "Vertical";
}
Button {
- Caption = Button;
- Width = Fit;
+ Caption = "Button";
+ Width = "Fit";
}
Label {
- Height = Fit;
- Width = Fit;
- Margin = 0;
+ Height = "Fit";
+ Width = "Fit";
+ Margin = "0";
}
Menu {
- Margin = 1;
- Background = vgradient|0:DimGray|1:Onyx;
- Height = Fit;
- Width = Stretched;
- VerticalAlignment = Top;
- SelectionBackground = Transparent;
+ Margin = "1";
+ Background = "vgradient|0:DimGray|1:Onyx";
+ Height = "Fit";
+ Width = "Stretched";
+ VerticalAlignment = "Top";
+ SelectionBackground = "Transparent";
}
MenuItem {
- Caption = MenuItem;
- Width = Stretched;
- Height = Fit;
- Background = Transparent;
- Foreground = LightGray;
- MouseEnter = {Background = vgradient|0:UnitedNationsBlue|1:Onyx;Foreground=White;}
- MouseLeave = {Foreground=LightGray;Background=Transparent;}
- SelectionBackground = Transparent;
+ Caption = "MenuItem";
+ Width = "Stretched";
+ Height = "Fit";
+ Background = "Transparent";
+ Foreground = "LightGray";
+ MouseEnter = "{Background = vgradient|0:UnitedNationsBlue|1:Onyx;Foreground=White;}";
+ MouseLeave = "{Foreground=LightGray;Background=Transparent;}";
+ SelectionBackground = "Transparent";
}
Docker {
- AllowDrop = true;
+ AllowDrop = "true";
}
DockWindow {
- AllowDrag = true;
+ AllowDrag = "true";
}
MessageBox {
- Background = 0.3,0.3,0.3,0.3;
- Width = Fit;
- Title=MessageBox;
- Font = serif, 12;
- MinimumSize = 200,120;
- AlwaysOnTop = true;
+ Background = "0.3,0.3,0.3,0.3";
+ Width = "Fit";
+ Caption="MessageBox";
+ Font = "serif, 12";
+ MinimumSize = "200,120";
+ AlwaysOnTop = "true";
}
Slider {
- Background = vgradient|0:Black|0.1:Gray|0.9:Gray|1:LightGray;
- Foreground = Gray;
- Width = Fit;
+ Background = "vgradient|0:Black|0.1:Gray|0.9:Gray|1:LightGray";
+ Foreground = "Gray";
+ Width = "Fit";
}
Splitter {
- Focusable = true;
- Background = DimGray;
+ Focusable = "true";
+ Background = "DimGray";
}
Spinner {
- Foreground = DimGray;
+ Foreground = "DimGray";
}
TabView {
- CacheEnabled = false;
+ CacheEnabled = "false";
}
TabItem {
- Caption = TabItem;
- Focusable = true;
- CacheEnabled = false;
+ Caption = "TabItem";
+ Focusable = "true";
+ CacheEnabled = "false";
}
TextBox {
- Background = White;
- Foreground = Black;
- Selectable = True;
- Text = TextBox;
- Margin = 1;
+ Background = "White";
+ Foreground = "Black";
+ Selectable = "True";
+ Text = "TextBox";
+ Margin = "1";
}
Window {
- Caption = Window;
- Focusable = true;
- MinimumSize=5,5;
- Width = 150;
- Height = 150;
+ Caption = "Window";
+ Focusable = "true";
+ MinimumSize="5,5";
+ Width = "150";
+ Height = "150";
}
ToolWindow {
- Caption = Window;
- Template = #Crow.ToolWindow.template;
- Focusable = true;
- MinimumSize=50,50;
- Width = 150;
- Height = 150;
+ Caption = "Window";
+ Template = "#Crow.ToolWindow.template";
+ Focusable = "true";
+ MinimumSize="50,50";
+ Width = "150";
+ Height = "150";
}
DocksView {
- AllowDrop = true;
+ AllowDrop = "true";
}
DockingView {
- Focusable = true;
- AllowDrag = true;
+ Focusable = "true";
+ AllowDrag = "true";
}
FileDialog {
- Template = #Crow.FileDialog.template;
- AlwaysOnTop = true;
- Focusable = true;
- MinimumSize=50,50;
- Width = 500;
- Height = 300;
+ Template = "#Crow.FileDialog.template";
+ AlwaysOnTop = "true";
+ Focusable = "true";
+ MinimumSize="50,50";
+ Width = "500";
+ Height = "300";
}
ProgressBar {
- Foreground = vgradient|0:BlueCrayola|0.5:SkyBlue|1:BlueCrayola;
+ Foreground = "vgradient|0:BlueCrayola|0.5:SkyBlue|1:BlueCrayola";
}
ScrollBar {
- Maximum = 0;
- Value = 0;
+ Maximum = "0";
+ Value = "0";
}
Scroller {
- CacheEnabled = false;
+ CacheEnabled = "false";
}
Control {
- Margin=0;
- Spacing=3;
+ Margin="0";
+ Spacing="3";
}
SaturationValueSelector {
- Foreground=Red;
+ Foreground="Red";
}
HueSelector {
- ClipToClientRect=False;
+ ClipToClientRect="False";
}
ColorSpinner {
- Minimum = 0;
- Maximum = 255;
- SmallIncrement = 1;
+ Minimum = "0";
+ Maximum = "255";
+ SmallIncrement = "1";
}
HSVSpinner {
- Minimum = 0;
- Maximum = 1;
- SmallIncrement = 0.01;
+ Minimum = "0";
+ Maximum = "1";
+ SmallIncrement = "0.01";
}
TxtInFileDialog {
- Margine = 1;
- Font = droid, 12;
+ Margine = "1";
+ Font = "droid, 12";
}
CheckBoxAlt {
- Template= #Crow.Templates.CheckBox2.template;
- Background = Transparent;
- Checked={Background=DarkSlateGray;Foreground=LightGray;};
- Unchecked = {Background=Transparent;Foreground=DimGray;};
+ Template= "#Crow.Templates.CheckBox2.template";
+ Background = "Transparent";
+ Checked="{Background=DarkSlateGray;Foreground=LightGray;}";
+ Unchecked = "{Background=Transparent;Foreground=DimGray;}";
}
ArrowBut {
- MouseRepeat=true;
- Height=Fit;
- Width=Fit;
- Focusable=true;
- Foreground=Jet;
- Background=hgradient|0:Gray|1:Jet;
- MouseDown={Background=hgradient|0:White|0.4:BlueCrayola|1:Jet};
- MouseUp={Background=hgradient|0:Gray|1:Jet};
- MouseEnter={Foreground=Black};
- MouseLeave={Foreground=Jet};
+ MouseRepeat="true";
+ Height="Fit";
+ Width="Fit";
+ Focusable="true";
+ Foreground="Jet";
+ Background="hgradient|0:Gray|1:Jet";
+ MouseDown="{Background=hgradient|0:White|0.4:BlueCrayola|1:Jet}";
+ MouseUp="{Background=hgradient|0:Gray|1:Jet}";
+ MouseEnter="{Foreground=Black}";
+ MouseLeave="{Foreground=Jet}";
}
\ No newline at end of file
using System.Collections.Generic;
using System.IO;
using System.Reflection;
+using System.Text.RegularExpressions;
+using Crow.Coding;
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 readerState { classNames, propertyName, expression }
- readerState state = readerState.classNames;
+ enum States { init, classNames, members, value, endOfStatement }
+
+ States curState = States.init;
+
string resourceId;
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 rxNameStartChar = new Regex(@"_|\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}");
+ static Regex rxNameChar = 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()})); }
+ }
+ public bool nextCharIsValidCharName
+ {
+ get { return rxNameChar.IsMatch(new string(new char[]{PeekChar()})); }
+ }
+ #endregion
+
+ char ReadChar () {
+ column++;
+ return (Char)Read();
+ }
+ char PeekChar () {
+ return (Char)Peek();
+ }
+ void SkipWhiteSpaceAndLineBreak (){
+ while (!EndOfStream){
+ if (!PeekChar ().IsWhiteSpaceOrNewLine ())
+ break;
+ if (ReadChar () == '\n') {
+ line++;
+ column = 0;
+ }
+ }
+ }
+
public StyleReader (Dictionary<string, Style> styling, Stream stream, string resId)
: base(stream)
{
List<string> targetsClasses = new List<string> ();
string currentProperty = "";
- int curlyBracketCount = 0;
-
while (!EndOfStream) {
- char c = (Char)Read ();
- if (c == '/' && !EndOfStream) {
- if ((char)Peek () == '/') {//process comment, skip until newline
- ReadLine ();
- continue;
- }
- }
- switch (state) {
- case readerState.classNames:
- if (c.IsWhiteSpaceOrNewLine () || c == ',' || c == '{') {
- if (!string.IsNullOrEmpty (token))
- targetsClasses.Add (token);
- if (c == '{')
- state = readerState.propertyName;
- token = "";
- }else if (c=='='){
- //this file contains only properties,
- //resource Id (minus .style extention) will determine the single target class
- if (targetsClasses.Count > 1)
- throwParserException ("Unexpected token '='");
- else if (targetsClasses.Count == 1) {
- if (!string.IsNullOrEmpty (token))
- throwParserException ("Unexpected token '='");
- currentProperty = targetsClasses [0];
- targetsClasses [0] = styleKey;
- }else{
- if (string.IsNullOrEmpty (token))
- throwParserException ("Unexpected token '='");
- targetsClasses.Add (styleKey);
- currentProperty = token;
- token = "";
- }
- state = readerState.expression;
- }else
- token += c;
+ SkipWhiteSpaceAndLineBreak ();
+ if (EndOfStream)
break;
- case readerState.propertyName:
- if (c.IsWhiteSpaceOrNewLine () || c == '=') {
- if (!string.IsNullOrEmpty (token))
- currentProperty = token;
- if (c == '=')
- state = readerState.expression;
- token = "";
- }else if (c == '}'){
- if (!string.IsNullOrEmpty (token))
- throwParserException ("Unexpected token '" + c + "'");
- targetsClasses = new List<string> ();
- currentProperty = "";
- state = readerState.classNames;
- } else
- token += c;
+ switch (Peek()) {
+ case '/':
+ ReadChar ();
+ if (PeekChar () != '/')
+ throw new ParserException (line, column, "Unexpected char '/'");
+ ReadLine ();
+ break;
+ case ',':
+ ReadChar ();
+ if (!(curState == States.init || curState == States.classNames) || string.IsNullOrEmpty (token))
+ throw new ParserException (line, column, "Unexpected char ','");
+ targetsClasses.Add (token);
+ token = "";
+ curState = States.classNames;
+ break;
+ case '{':
+ ReadChar ();
+ if (!(curState == States.init || curState == States.classNames) || string.IsNullOrEmpty (token))
+ throw new ParserException (line, column, "Unexpected char '{'");
+ targetsClasses.Add (token);
+ token = "";
+ curState = States.members;
+ break;
+ case '}':
+ ReadChar ();
+ if (curState != States.members)
+ throw new ParserException (line, column, "Unexpected char '}'");
+ curState = States.classNames;
+ targetsClasses.Clear ();
+ break;
+ case '=':
+ ReadChar ();
+ if (!(curState == States.init || curState == States.members))
+ throw new ParserException (line, column, "Unexpected char '='");
+ currentProperty = token;
+ token = "";
+ curState = States.value;
break;
- case readerState.expression:
- bool expressionIsFinished = false;
- if (curlyBracketCount == 0) {
- if (c == '{'){
- if (!string.IsNullOrEmpty(token.Trim()))
- throwParserException ("Unexpected token '{'");
- curlyBracketCount++;
- token = "{";
- }else if (c == '}')
- throwParserException ("Unexpected token '{'");
- else if (c == ';') {
- expressionIsFinished = true;
- } else
- token += c;
- } else {
- if (c == '{')
- curlyBracketCount++;
- else if (c == '}') {
- curlyBracketCount--;
- if (curlyBracketCount == 0)
- expressionIsFinished = true;
+ case '"':
+ if (curState != States.value)
+ throw new ParserException (line, column, "Unexpected char '\"'");
+ ReadChar ();
+
+ while (!EndOfStream) {
+ char c = PeekChar();
+ if (c == '\"') {
+ ReadChar ();
+ break;
}
- token += c;
+ token += ReadChar();
+ if (c == '\\' && !EndOfStream)
+ token += ReadChar();
+ }
+ curState = States.endOfStatement;
+ break;
+ case ';':
+ if (curState != States.endOfStatement)
+ throw new ParserException (line, column, "Unexpected end of statement");
+ 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;
+ System.Diagnostics.Debug.WriteLine ("Style: {0}.{1} = {2}", tc, currentProperty, token);
}
- if (expressionIsFinished) {
- if (!string.IsNullOrEmpty (token)) {
- string expression = token.Trim ();
+ token = "";
+ curState = States.members;
+ break;
+ default:
+ if (curState == States.value)
+ throw new ParserException (line, column, "expecting value enclosed in '\"'");
+ if (curState == States.endOfStatement)
+ throw new ParserException (line, column, "expecting end of statement");
- foreach (string tc in targetsClasses) {
- if (!styling.ContainsKey (tc))
- styling [tc] = new Style ();
- else if (styling [tc].ContainsKey (currentProperty))
- continue;
- styling [tc] [currentProperty] = expression;
- }
- token = "";
- }
- //allow omiting ';' if curly bracket close expression
- while (!EndOfStream) {
- if (Char.IsWhiteSpace((char)Peek()))
- Read();
- else
- break;
- }
- if (this.Peek () == ';')
- this.Read ();
- state = readerState.propertyName;
+ if (nextCharIsValidCharStartName) {
+ token += ReadChar();
+ while (nextCharIsValidCharName)
+ token += ReadChar();
}
break;
}
}
-
- if (curlyBracketCount > 0)
- throwParserException ("Unexpected end of file");
}
public override int Read ()