diff --git a/include/eepp/ui/css/stylesheet.hpp b/include/eepp/ui/css/stylesheet.hpp new file mode 100644 index 000000000..91f036c9c --- /dev/null +++ b/include/eepp/ui/css/stylesheet.hpp @@ -0,0 +1,21 @@ +#ifndef EE_UI_CSS_STYLESHEET_HPP +#define EE_UI_CSS_STYLESHEET_HPP + +#include + +namespace EE { namespace UI { namespace CSS { + +class StyleSheet { + public: + StyleSheet(); + + void addNode( StyleSheetNode node ); + + StyleSheetProperties find( const std::string& tagName = "", const std::string& id = "", const std::vector& classes = {}, const std::string& pseudoClass = "" ); + + std::vector nodes; +}; + +}}} + +#endif diff --git a/include/eepp/ui/css/stylesheetelement.hpp b/include/eepp/ui/css/stylesheetelement.hpp new file mode 100644 index 000000000..566ad203a --- /dev/null +++ b/include/eepp/ui/css/stylesheetelement.hpp @@ -0,0 +1,21 @@ +#ifndef EE_UI_CSS_STYLESHEETELEMENT_HPP +#define EE_UI_CSS_STYLESHEETELEMENT_HPP + +#include +#include + +namespace EE { namespace UI { namespace CSS { + +class StyleSheetElement { + public: + virtual std::string getStyleSheetTag() const = 0; + + virtual const std::string& getStyleSheetId() const; + + virtual const std::vector& getStyleSheetClasses() = 0; + + virtual StyleSheetElement * getStyleSheetParentElement() = 0; +}; +}}} + +#endif diff --git a/include/eepp/ui/css/stylesheetnode.hpp b/include/eepp/ui/css/stylesheetnode.hpp new file mode 100644 index 000000000..dbf99ad31 --- /dev/null +++ b/include/eepp/ui/css/stylesheetnode.hpp @@ -0,0 +1,21 @@ +#ifndef EE_UI_CSS_STYLESHEETNODE_HPP +#define EE_UI_CSS_STYLESHEETNODE_HPP + +#include +#include + +namespace EE { namespace UI { namespace CSS { + +class StyleSheetNode { + public: + explicit StyleSheetNode( const std::string& selector, const StyleSheetProperties& properties ); + + void print(); + + StyleSheetSelector selector; + StyleSheetProperties properties; +}; + +}}} + +#endif diff --git a/include/eepp/ui/css/stylesheetparser.hpp b/include/eepp/ui/css/stylesheetparser.hpp index 2ff73c67a..3e6f7a7a4 100644 --- a/include/eepp/ui/css/stylesheetparser.hpp +++ b/include/eepp/ui/css/stylesheetparser.hpp @@ -1,271 +1,20 @@ #ifndef EE_UI_CSS_STYLESHEETPARSER #define EE_UI_CSS_STYLESHEETPARSER -#include -#include #include #include +#include +#include +#include +#include +#include +#include #include -#include using namespace EE; using namespace EE::System; namespace EE { namespace UI { namespace CSS { -// This is not how it should be. -class StyleSheetSelector { - public: - enum SelectorType { - TagName = 1 << 0, - Id = 1 << 1, - Class = 1 << 2, - PseudoClass = 1 << 3 - }; - - enum SpecificityVal { - SpecificityId = 1000000, - SpecificityClass = 100000, - SpecificityTag = 10000, - SpecificityPseudoClass = 0 - }; - - explicit StyleSheetSelector( const std::string& selectorName ) : - name( selectorName ), - specificity(0) - { - auto parts = String::split( name, ' ' ); - - for ( auto it = parts.begin(); it != parts.end(); ++it ) { - parseSelector( *it ); - } - } - - Uint32 getRequiredFlags() { - Uint32 flags = 0; - - if ( hasTagName() ) - flags |= TagName; - - if ( hasId() ) - flags |= Id; - - if ( hasClasses() ) - flags |= Class; - - if ( hasPseudoClass() ) - flags |= PseudoClass; - - return flags; - } - - const std::string& getName() const { return name; }; - - const std::string& getTagName() const { return tagName; } - - const std::string getId() const { return id; } - - const std::vector getClasses() const { return classes; } - - const std::string& getPseudoClass() const; - - bool hasTagName() { return !tagName.empty(); } - - bool hasId() { return !id.empty(); } - - bool hasClasses() { return !classes.empty(); } - - bool hasClass( std::string cls ) { return std::find(classes.begin(), classes.end(), cls) != classes.end(); } - - bool hasPseudoClass() { return !pseudoClass.empty(); } - - Uint32 getSpecificity() { return specificity; } - protected: - std::string name; - std::string tagName; - std::string id; - std::vector classes; - std::string pseudoClass; - Uint32 specificity; - - void parseSelector( const std::string& selector ) { - auto selPseudo = String::split( selector, ':' ); - - if ( !selPseudo.empty() ) { - std::string rselector( selPseudo[0] ); - - if ( !rselector.empty() ) { - if ( rselector[0] == '.' ) { - classes.push_back( rselector.substr(1) ); - specificity += SpecificityClass; - } else if ( selector[0] == '#' ) { - id = rselector.substr(1); - specificity += SpecificityId; - } else { - tagName = rselector; - specificity += SpecificityTag; - } - } - - if ( selPseudo.size() > 1 ) { - pseudoClass = selPseudo[1]; - specificity += SpecificityPseudoClass; - } - } - } -}; - -class StyleSheetProperty { - public: - StyleSheetProperty() - {} - - explicit StyleSheetProperty( const std::string& name, const std::string& value ) : - name( String::trim( name ) ), - value( String::trim( value ) ) - {} - - std::string name; - std::string value; -}; - -typedef std::map StyleSheetProperties; - -class StyleSheetSelectorParser { - public: - StyleSheetSelectorParser(){} - - explicit StyleSheetSelectorParser( std::string name ) - { - std::vector sels = String::split( name, ',' ); - - for ( std::vector::iterator it = sels.begin(); it != sels.end(); ++it ) - { - std::string cur = String::trim( *it ); - - selectors.push_back( StyleSheetSelector( cur ) ); - } - } - - std::vector selectors; -}; - -class StyleSheetPropertiesParser { - public: - typedef std::map PropertiesDictionary; - - StyleSheetPropertiesParser(){} - - explicit StyleSheetPropertiesParser( const std::string& propsstr ) { - std::vector props = String::split( propsstr, ';' ); - - if ( !props.empty() ) { - parse( propsstr ); - } - }; - - void print(); - - PropertiesDictionary properties; - protected: - enum ReadState { - ReadingPropertyName, - ReadingPropertyValue, - ReadingValueUrl, - ReadingComment - }; - - ReadState prevRs; - - void parse( std::string propsstr ); - - int readPropertyName( ReadState& rs, std::size_t pos, std::string& buffer, const std::string& str ); - - int readPropertyValue( ReadState& rs, std::size_t pos, std::string& buffer, const std::string& str ); - - int readComment( ReadState& rs, std::size_t pos, std::string& buffer, const std::string& str ); - - int readValueUrl( ReadState& rs, std::size_t pos, std::string& buffer, const std::string& str ); -}; - -class StyleSheetNode { - public: - explicit StyleSheetNode( const std::string& selector, const StyleSheetProperties& properties ) : - selector( selector ), - properties( properties ) - {} - - void print() { - std::cout << selector.getName() << " {" << std::endl; - - for ( StyleSheetProperties::iterator it = properties.begin(); it != properties.end(); ++it ) { - StyleSheetProperty& prop = it->second; - - std::cout << "\t" << prop.name << ": " << prop.value << ";" << std::endl; - } - - std::cout << "}" << std::endl; - } - - StyleSheetSelector selector; - StyleSheetProperties properties; -}; - -class StyleSheet { - public: - StyleSheet() {} - - void addNode( StyleSheetNode node ) { - nodes.push_back( node ); - } - - StyleSheetProperties find( const std::string& tagName = "", const std::string& id = "", const std::vector& classes = {}, const std::string& pseudoClass = "" ) { - StyleSheetProperties propertiesSelected; - Uint32 lastSpecificity = -1; - - for ( auto it = nodes.begin(); it != nodes.end(); ++it ) { - StyleSheetNode& node = *it; - StyleSheetSelector& selector = node.selector; - - Uint32 flags = 0; - - if ( selector.hasTagName() && !tagName.empty() && selector.getTagName() == tagName ) { - flags |= StyleSheetSelector::TagName; - } - - if ( selector.hasId() && !id.empty() && selector.getId() == id ) { - flags |= StyleSheetSelector::Id; - } - - if ( selector.hasClasses() && !classes.empty() ) { - bool hasClasses = true; - for ( auto cit = classes.begin(); cit != classes.end(); ++cit ) { - if ( !selector.hasClass( *cit ) ) { - hasClasses = false; - break; - } - } - - if ( hasClasses ) { - flags |= StyleSheetSelector::Class; - } - } - - if ( selector.hasPseudoClass() && !pseudoClass.empty() && selector.getPseudoClass() == pseudoClass ) { - flags |= StyleSheetSelector::PseudoClass; - } - - if ( flags == selector.getRequiredFlags() && selector.getSpecificity() > lastSpecificity ) { - propertiesSelected = node.properties; - lastSpecificity = selector.getSpecificity(); - } - } - - return propertiesSelected; - } - - std::vector nodes; -}; - class StyleSheetParser { public: StyleSheetParser(); @@ -275,6 +24,8 @@ class StyleSheetParser { bool loadFromFile( const std::string& file ); void print(); + + StyleSheet& getStyleSheet(); protected: enum ReadState { ReadingStyle, diff --git a/include/eepp/ui/css/stylesheetpropertiesparser.hpp b/include/eepp/ui/css/stylesheetpropertiesparser.hpp new file mode 100644 index 000000000..893f46bc2 --- /dev/null +++ b/include/eepp/ui/css/stylesheetpropertiesparser.hpp @@ -0,0 +1,43 @@ +#ifndef EE_UI_CSS_STYLESHEETPROPERTIESPARSER_HPP +#define EE_UI_CSS_STYLESHEETPROPERTIESPARSER_HPP + +#include +#include +#include +#include + +namespace EE { namespace UI { namespace CSS { + +class StyleSheetPropertiesParser { + public: + StyleSheetPropertiesParser(); + + explicit StyleSheetPropertiesParser( const std::string& propsstr ); + + void print(); + + StyleSheetProperties properties; + protected: + enum ReadState { + ReadingPropertyName, + ReadingPropertyValue, + ReadingValueUrl, + ReadingComment + }; + + ReadState prevRs; + + void parse( std::string propsstr ); + + int readPropertyName( ReadState& rs, std::size_t pos, std::string& buffer, const std::string& str ); + + int readPropertyValue( ReadState& rs, std::size_t pos, std::string& buffer, const std::string& str ); + + int readComment( ReadState& rs, std::size_t pos, std::string& buffer, const std::string& str ); + + int readValueUrl( ReadState& rs, std::size_t pos, std::string& buffer, const std::string& str ); +}; + +}}} + +#endif diff --git a/include/eepp/ui/css/stylesheetproperty.hpp b/include/eepp/ui/css/stylesheetproperty.hpp new file mode 100644 index 000000000..98f1a351e --- /dev/null +++ b/include/eepp/ui/css/stylesheetproperty.hpp @@ -0,0 +1,24 @@ +#ifndef EE_UI_CSS_STYLESHEETPROPERTY_HPP +#define EE_UI_CSS_STYLESHEETPROPERTY_HPP + +#include +#include + +namespace EE { namespace UI { namespace CSS { + +class StyleSheetProperty { + public: + StyleSheetProperty(); + + explicit StyleSheetProperty( const std::string& name, const std::string& value ); + + std::string name; + std::string value; +}; + +typedef std::map StyleSheetProperties; +typedef std::map PropertiesDictionary; + +}}} + +#endif diff --git a/include/eepp/ui/css/stylesheetselector.hpp b/include/eepp/ui/css/stylesheetselector.hpp new file mode 100644 index 000000000..c43dc2e28 --- /dev/null +++ b/include/eepp/ui/css/stylesheetselector.hpp @@ -0,0 +1,62 @@ +#ifndef EE_UI_CSS_STYLESHEETSELECTOR_HPP +#define EE_UI_CSS_STYLESHEETSELECTOR_HPP + +#include + +namespace EE { namespace UI { namespace CSS { + +class StyleSheetSelector { + public: + enum SelectorType { + TagName = 1 << 0, + Id = 1 << 1, + Class = 1 << 2, + PseudoClass = 1 << 3 + }; + + enum SpecificityVal { + SpecificityId = 1000000, + SpecificityClass = 100000, + SpecificityTag = 10000, + SpecificityPseudoClass = 0 + }; + + explicit StyleSheetSelector( const std::string& selectorName ); + + Uint32 getRequiredFlags(); + + const std::string& getName() const; + + const std::string& getTagName() const; + + const std::string getId() const; + + const std::vector getClasses() const; + + const std::string& getPseudoClass() const; + + bool hasTagName(); + + bool hasId(); + + bool hasClasses(); + + bool hasClass( std::string cls ); + + bool hasPseudoClass(); + + Uint32 getSpecificity(); + protected: + std::string name; + std::string tagName; + std::string id; + std::vector classes; + std::string pseudoClass; + Uint32 specificity; + + void parseSelector( const std::string& selector ); +}; + +}}} + +#endif diff --git a/include/eepp/ui/css/stylesheetselectorparser.hpp b/include/eepp/ui/css/stylesheetselectorparser.hpp new file mode 100644 index 000000000..1e0b1c07d --- /dev/null +++ b/include/eepp/ui/css/stylesheetselectorparser.hpp @@ -0,0 +1,18 @@ +#ifndef EE_UI_CSS_STYLESHEETSELECTORPARSER_HPP +#define EE_UI_CSS_STYLESHEETSELECTORPARSER_HPP + +#include + +namespace EE { namespace UI { namespace CSS { + +class StyleSheetSelectorParser { + public: + StyleSheetSelectorParser(); + + explicit StyleSheetSelectorParser( std::string name ); + + std::vector selectors; +}; + +}}} +#endif diff --git a/projects/linux/ee.files b/projects/linux/ee.files index 7835f89a8..6212629b4 100644 --- a/projects/linux/ee.files +++ b/projects/linux/ee.files @@ -293,7 +293,14 @@ ../../include/eepp/thirdparty/PlusCallback/callback.hpp ../../include/eepp/ui/base.hpp ../../include/eepp/ui.hpp +../../include/eepp/ui/css/stylesheet.hpp +../../include/eepp/ui/css/stylesheetelement.hpp +../../include/eepp/ui/css/stylesheetnode.hpp ../../include/eepp/ui/css/stylesheetparser.hpp +../../include/eepp/ui/css/stylesheetpropertiesparser.hpp +../../include/eepp/ui/css/stylesheetproperty.hpp +../../include/eepp/ui/css/stylesheetselector.hpp +../../include/eepp/ui/css/stylesheetselectorparser.hpp ../../include/eepp/ui/marginmove/scale.hpp ../../include/eepp/ui/tools/textureatlaseditor.hpp ../../include/eepp/ui/uicheckbox.hpp @@ -693,7 +700,13 @@ ../../src/eepp/system/translator.cpp ../../src/eepp/system/virtualfilesystem.cpp ../../src/eepp/system/zip.cpp +../../src/eepp/ui/css/stylesheet.cpp +../../src/eepp/ui/css/stylesheetnode.cpp ../../src/eepp/ui/css/stylesheetparser.cpp +../../src/eepp/ui/css/stylesheetpropertiesparser.cpp +../../src/eepp/ui/css/stylesheetproperty.cpp +../../src/eepp/ui/css/stylesheetselector.cpp +../../src/eepp/ui/css/stylesheetselectorparser.cpp ../../src/eepp/ui/tools/textureatlaseditor.cpp ../../src/eepp/ui/tools/textureatlasnew.cpp ../../src/eepp/ui/tools/textureatlasnew.hpp diff --git a/src/eepp/ui/css/stylesheet.cpp b/src/eepp/ui/css/stylesheet.cpp new file mode 100644 index 000000000..7c9ab3a49 --- /dev/null +++ b/src/eepp/ui/css/stylesheet.cpp @@ -0,0 +1,58 @@ +#include +#include +#include + +namespace EE { namespace UI { namespace CSS { + +StyleSheet::StyleSheet() {} + +void StyleSheet::addNode( StyleSheetNode node ) { + nodes.push_back( node ); +} + +StyleSheetProperties StyleSheet::find( const std::string& tagName, const std::string& id, const std::vector& classes, const std::string& pseudoClass ) { + StyleSheetProperties propertiesSelected; + Uint32 lastSpecificity = -1; + + for ( auto it = nodes.begin(); it != nodes.end(); ++it ) { + StyleSheetNode& node = *it; + StyleSheetSelector& selector = node.selector; + + Uint32 flags = 0; + + if ( selector.hasTagName() && !tagName.empty() && selector.getTagName() == tagName ) { + flags |= StyleSheetSelector::TagName; + } + + if ( selector.hasId() && !id.empty() && selector.getId() == id ) { + flags |= StyleSheetSelector::Id; + } + + if ( selector.hasClasses() && !classes.empty() ) { + bool hasClasses = true; + for ( auto cit = classes.begin(); cit != classes.end(); ++cit ) { + if ( !selector.hasClass( *cit ) ) { + hasClasses = false; + break; + } + } + + if ( hasClasses ) { + flags |= StyleSheetSelector::Class; + } + } + + if ( selector.hasPseudoClass() && !pseudoClass.empty() && selector.getPseudoClass() == pseudoClass ) { + flags |= StyleSheetSelector::PseudoClass; + } + + if ( flags == selector.getRequiredFlags() && selector.getSpecificity() > lastSpecificity ) { + propertiesSelected = node.properties; + lastSpecificity = selector.getSpecificity(); + } + } + + return propertiesSelected; +} + +}}} diff --git a/src/eepp/ui/css/stylesheetnode.cpp b/src/eepp/ui/css/stylesheetnode.cpp new file mode 100644 index 000000000..c78ffa4e8 --- /dev/null +++ b/src/eepp/ui/css/stylesheetnode.cpp @@ -0,0 +1,23 @@ +#include +#include + +namespace EE { namespace UI { namespace CSS { + +StyleSheetNode::StyleSheetNode( const std::string& selector, const StyleSheetProperties& properties ) : + selector( selector ), + properties( properties ) +{} + +void StyleSheetNode::print() { + std::cout << selector.getName() << " {" << std::endl; + + for ( StyleSheetProperties::iterator it = properties.begin(); it != properties.end(); ++it ) { + StyleSheetProperty& prop = it->second; + + std::cout << "\t" << prop.name << ": " << prop.value << ";" << std::endl; + } + + std::cout << "}" << std::endl; +} + +}}} diff --git a/src/eepp/ui/css/stylesheetparser.cpp b/src/eepp/ui/css/stylesheetparser.cpp index fc9a10960..07f784b62 100644 --- a/src/eepp/ui/css/stylesheetparser.cpp +++ b/src/eepp/ui/css/stylesheetparser.cpp @@ -1,151 +1,10 @@ #include +#include +#include #include namespace EE { namespace UI { namespace CSS { -void StyleSheetPropertiesParser::parse( std::string propsstr ) { - ReadState rs = ReadingPropertyName; - prevRs = rs; - std::size_t pos = 0; - std::string buffer; - - while ( pos < propsstr.size() ) { - switch (rs) { - case ReadingPropertyName: - { - pos = readPropertyName(rs, pos, buffer, propsstr); - break; - } - case ReadingPropertyValue: - { - pos = readPropertyValue(rs, pos, buffer, propsstr); - break; - } - case ReadingComment: - { - pos = readComment(rs, pos, buffer, propsstr); - } - default: - break; - } - } -} - -int StyleSheetPropertiesParser::readPropertyName(StyleSheetPropertiesParser::ReadState & rs, std::size_t pos, std::string & buffer, const std::string& str) { - prevRs = rs; - buffer.clear(); - - while ( pos < str.size() ) { - if ( str[pos] == '/' && str.size() > pos + 1 && str[pos+1] == '*' ) { - rs = ReadingComment; - return pos; - } - - if ( str[pos] == ':' ) { - rs = ReadingPropertyValue; - return pos + 1; - } - - if ( str[pos] != '\n' && str[pos] != '\t' ) - buffer += str[pos]; - - pos++; - } - - return pos; -} - -int StyleSheetPropertiesParser::readPropertyValue(StyleSheetPropertiesParser::ReadState & rs, std::size_t pos, std::string & buffer, const std::string& str) { - std::string propName( buffer ); - - buffer.clear(); - - prevRs = rs; - - while ( pos < str.size() ) { - if ( str[pos] == '/' && str.size() > pos + 1 && str[pos+1] == '*' ) { - rs = ReadingComment; - return pos; - } - - if ( buffer.size() == 4 && buffer.substr(0,4) == "url(" ) { - rs = ReadingValueUrl; - pos = readValueUrl( rs, pos, buffer, str ); - } - - if ( str[pos] == ';' ) { - rs = ReadingPropertyName; - - properties[ propName ] = StyleSheetProperty( propName, buffer ); - - return pos + 1; - } - - if ( str[pos] != '\n' && str[pos] != '\t' ) - buffer += str[pos]; - - pos++; - - if ( pos == str.size() ) { - rs = ReadingPropertyName; - - properties[ propName ] = StyleSheetProperty( propName, buffer ); - - return pos + 1; - } - } - - return pos; -} - -int StyleSheetPropertiesParser::readComment(StyleSheetPropertiesParser::ReadState & rs, std::size_t pos, std::string & buffer, const std::string & str) { - buffer.clear(); - - while ( pos < str.size() ) { - if ( str[pos] == '*' && str.size() > pos + 1 && str[pos+1] == '/' ) { - rs = prevRs; - return pos + 2; - } - - buffer += str[pos]; - - pos++; - } - - return pos; -} - -int StyleSheetPropertiesParser::readValueUrl(StyleSheetPropertiesParser::ReadState & rs, std::size_t pos, std::string & buffer, const std::string& str) { - bool quoted = false; - - while ( pos < str.size() ) { - if ( !quoted && str[pos] == '"' ) { - buffer += str[pos]; - - quoted = true; - } else if ( !quoted ) { - if ( str[pos] != '\n' && str[pos] != '\t' ) - buffer += str[pos]; - - if ( str[pos] == ')' ) { - rs = ReadingPropertyValue; - return pos + 1; - } - } - else { - buffer += str[pos]; - - if ( quoted && str[pos] == '"' ) { - quoted = false; - } - } - - pos++; - } - - return pos; -} - StyleSheetParser::StyleSheetParser() { } @@ -168,6 +27,10 @@ void StyleSheetParser::print() { } } +StyleSheet &StyleSheetParser::getStyleSheet() { + return mStyleSheet; +} + bool StyleSheetParser::parse() { ReadState rs = ReadingStyle; std::size_t pos = 0; diff --git a/src/eepp/ui/css/stylesheetpropertiesparser.cpp b/src/eepp/ui/css/stylesheetpropertiesparser.cpp new file mode 100644 index 000000000..1e007cb0b --- /dev/null +++ b/src/eepp/ui/css/stylesheetpropertiesparser.cpp @@ -0,0 +1,158 @@ +#include + +namespace EE { namespace UI { namespace CSS { + +StyleSheetPropertiesParser::StyleSheetPropertiesParser(){} + +StyleSheetPropertiesParser::StyleSheetPropertiesParser( const std::string& propsstr ) { + std::vector props = String::split( propsstr, ';' ); + + if ( !props.empty() ) { + parse( propsstr ); + } +}; + +void StyleSheetPropertiesParser::parse( std::string propsstr ) { + ReadState rs = ReadingPropertyName; + prevRs = rs; + std::size_t pos = 0; + std::string buffer; + + while ( pos < propsstr.size() ) { + switch (rs) { + case ReadingPropertyName: + { + pos = readPropertyName(rs, pos, buffer, propsstr); + break; + } + case ReadingPropertyValue: + { + pos = readPropertyValue(rs, pos, buffer, propsstr); + break; + } + case ReadingComment: + { + pos = readComment(rs, pos, buffer, propsstr); + } + default: + break; + } + } +} + +int StyleSheetPropertiesParser::readPropertyName(StyleSheetPropertiesParser::ReadState & rs, std::size_t pos, std::string & buffer, const std::string& str) { + prevRs = rs; + buffer.clear(); + + while ( pos < str.size() ) { + if ( str[pos] == '/' && str.size() > pos + 1 && str[pos+1] == '*' ) { + rs = ReadingComment; + return pos; + } + + if ( str[pos] == ':' ) { + rs = ReadingPropertyValue; + return pos + 1; + } + + if ( str[pos] != '\n' && str[pos] != '\t' ) + buffer += str[pos]; + + pos++; + } + + return pos; +} + +int StyleSheetPropertiesParser::readPropertyValue(StyleSheetPropertiesParser::ReadState & rs, std::size_t pos, std::string & buffer, const std::string& str) { + std::string propName( buffer ); + + buffer.clear(); + + prevRs = rs; + + while ( pos < str.size() ) { + if ( str[pos] == '/' && str.size() > pos + 1 && str[pos+1] == '*' ) { + rs = ReadingComment; + return pos; + } + + if ( buffer.size() == 4 && buffer.substr(0,4) == "url(" ) { + rs = ReadingValueUrl; + pos = readValueUrl( rs, pos, buffer, str ); + } + + if ( str[pos] == ';' ) { + rs = ReadingPropertyName; + + properties[ propName ] = StyleSheetProperty( propName, buffer ); + + return pos + 1; + } + + if ( str[pos] != '\n' && str[pos] != '\t' ) + buffer += str[pos]; + + pos++; + + if ( pos == str.size() ) { + rs = ReadingPropertyName; + + properties[ propName ] = StyleSheetProperty( propName, buffer ); + + return pos + 1; + } + } + + return pos; +} + +int StyleSheetPropertiesParser::readComment(StyleSheetPropertiesParser::ReadState & rs, std::size_t pos, std::string & buffer, const std::string & str) { + buffer.clear(); + + while ( pos < str.size() ) { + if ( str[pos] == '*' && str.size() > pos + 1 && str[pos+1] == '/' ) { + rs = prevRs; + return pos + 2; + } + + buffer += str[pos]; + + pos++; + } + + return pos; +} + +int StyleSheetPropertiesParser::readValueUrl(StyleSheetPropertiesParser::ReadState & rs, std::size_t pos, std::string & buffer, const std::string& str) { + bool quoted = false; + + while ( pos < str.size() ) { + if ( !quoted && str[pos] == '"' ) { + buffer += str[pos]; + + quoted = true; + } else if ( !quoted ) { + if ( str[pos] != '\n' && str[pos] != '\t' ) + buffer += str[pos]; + + if ( str[pos] == ')' ) { + rs = ReadingPropertyValue; + return pos + 1; + } + } + else { + buffer += str[pos]; + + if ( quoted && str[pos] == '"' ) { + quoted = false; + } + } + + pos++; + } + + return pos; +} + +}}} diff --git a/src/eepp/ui/css/stylesheetproperty.cpp b/src/eepp/ui/css/stylesheetproperty.cpp new file mode 100644 index 000000000..a5f21fb14 --- /dev/null +++ b/src/eepp/ui/css/stylesheetproperty.cpp @@ -0,0 +1,14 @@ +#include +#include + +namespace EE { namespace UI { namespace CSS { + +StyleSheetProperty::StyleSheetProperty() +{} + +StyleSheetProperty::StyleSheetProperty( const std::string& name, const std::string& value ) : + name( String::trim( name ) ), + value( String::trim( value ) ) +{} + +}}} diff --git a/src/eepp/ui/css/stylesheetselector.cpp b/src/eepp/ui/css/stylesheetselector.cpp new file mode 100644 index 000000000..aa7ba5c7c --- /dev/null +++ b/src/eepp/ui/css/stylesheetselector.cpp @@ -0,0 +1,84 @@ +#include +#include + +namespace EE { namespace UI { namespace CSS { + + +StyleSheetSelector::StyleSheetSelector( const std::string& selectorName ) : + name( selectorName ), + specificity(0) +{ + auto parts = String::split( name, ' ' ); + + for ( auto it = parts.begin(); it != parts.end(); ++it ) { + parseSelector( *it ); + } +} + +Uint32 StyleSheetSelector::getRequiredFlags() { + Uint32 flags = 0; + + if ( hasTagName() ) + flags |= TagName; + + if ( hasId() ) + flags |= Id; + + if ( hasClasses() ) + flags |= Class; + + if ( hasPseudoClass() ) + flags |= PseudoClass; + + return flags; +} + +const std::string& StyleSheetSelector::getName() const { return name; }; + +const std::string& StyleSheetSelector::getTagName() const { return tagName; } + +const std::string StyleSheetSelector::getId() const { return id; } + +const std::vector StyleSheetSelector::getClasses() const { return classes; } + +const std::string& StyleSheetSelector::getPseudoClass() const { return pseudoClass; }; + +bool StyleSheetSelector::hasTagName() { return !tagName.empty(); } + +bool StyleSheetSelector::hasId() { return !id.empty(); } + +bool StyleSheetSelector::hasClasses() { return !classes.empty(); } + +bool StyleSheetSelector::hasClass( std::string cls ) { return std::find(classes.begin(), classes.end(), cls) != classes.end(); } + +bool StyleSheetSelector::hasPseudoClass() { return !pseudoClass.empty(); } + +Uint32 StyleSheetSelector::getSpecificity() { return specificity; } + +void StyleSheetSelector::parseSelector( const std::string& selector ) { + auto selPseudo = String::split( selector, ':' ); + + if ( !selPseudo.empty() ) { + std::string rselector( selPseudo[0] ); + + if ( !rselector.empty() ) { + if ( rselector[0] == '.' ) { + classes.push_back( rselector.substr(1) ); + specificity += SpecificityClass; + } else if ( selector[0] == '#' ) { + id = rselector.substr(1); + specificity += SpecificityId; + } else { + tagName = rselector; + specificity += SpecificityTag; + } + } + + if ( selPseudo.size() > 1 ) { + pseudoClass = selPseudo[1]; + specificity += SpecificityPseudoClass; + } + } +} + +}}} diff --git a/src/eepp/ui/css/stylesheetselectorparser.cpp b/src/eepp/ui/css/stylesheetselectorparser.cpp new file mode 100644 index 000000000..9128ba9e0 --- /dev/null +++ b/src/eepp/ui/css/stylesheetselectorparser.cpp @@ -0,0 +1,19 @@ +#include + +namespace EE { namespace UI { namespace CSS { + +StyleSheetSelectorParser::StyleSheetSelectorParser(){} + +StyleSheetSelectorParser::StyleSheetSelectorParser( std::string name ) +{ + std::vector sels = String::split( name, ',' ); + + for ( std::vector::iterator it = sels.begin(); it != sels.end(); ++it ) + { + std::string cur = String::trim( *it ); + + selectors.push_back( StyleSheetSelector( cur ) ); + } +} + +}}}