Browse Source

LibWeb: Implement and use FlexFlowStyleValue

Sam Atkins 3 years ago
parent
commit
c27f99fc1d

+ 61 - 0
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -1981,6 +1981,63 @@ RefPtr<StyleValue> Parser::parse_flex_value(ParsingContext const& context, Vecto
     return FlexStyleValue::create(flex_grow.release_nonnull(), flex_shrink.release_nonnull(), flex_basis.release_nonnull());
 }
 
+RefPtr<StyleValue> Parser::parse_flex_flow_value(ParsingContext const& context, Vector<StyleComponentValueRule> const& component_values)
+{
+    auto is_flex_direction = [](StyleValue const& value) -> bool {
+        switch (value.to_identifier()) {
+        case ValueID::Row:
+        case ValueID::RowReverse:
+        case ValueID::Column:
+        case ValueID::ColumnReverse:
+            return true;
+        default:
+            return false;
+        }
+    };
+
+    auto is_flex_wrap = [](StyleValue const& value) -> bool {
+        switch (value.to_identifier()) {
+        case ValueID::Wrap:
+        case ValueID::Nowrap:
+        case ValueID::WrapReverse:
+            return true;
+        default:
+            return false;
+        }
+    };
+
+    if (component_values.size() > 2)
+        return nullptr;
+
+    RefPtr<StyleValue> flex_direction;
+    RefPtr<StyleValue> flex_wrap;
+
+    for (auto& part : component_values) {
+        auto value = Parser::parse_css_value(context, PropertyID::FlexFlow, part);
+        if (!value)
+            return nullptr;
+        if (is_flex_direction(*value)) {
+            if (flex_direction)
+                return nullptr;
+            flex_direction = value.release_nonnull();
+            continue;
+        }
+        if (is_flex_wrap(*value)) {
+            if (flex_wrap)
+                return nullptr;
+            flex_wrap = value.release_nonnull();
+            continue;
+        }
+    }
+
+    if (!flex_direction)
+        flex_direction = IdentifierStyleValue::create(ValueID::Row);
+    if (!flex_wrap)
+        flex_wrap = IdentifierStyleValue::create(ValueID::Nowrap);
+
+    return FlexFlowStyleValue::create(flex_direction.release_nonnull(), flex_wrap.release_nonnull());
+}
+
 RefPtr<StyleValue> Parser::parse_font_value(ParsingContext const& context, Vector<StyleComponentValueRule> const& component_values)
 {
     auto is_font_size = [](StyleValue const& value) -> bool {
@@ -2381,6 +2438,10 @@ RefPtr<StyleValue> Parser::parse_css_value(PropertyID property_id, TokenStream<S
         if (auto parsed_value = parse_flex_value(m_context, component_values))
             return parsed_value;
         break;
+    case PropertyID::FlexFlow:
+        if (auto parsed_value = parse_flex_flow_value(m_context, component_values))
+            return parsed_value;
+        break;
     case PropertyID::Font:
         if (auto parsed_value = parse_font_value(m_context, component_values))
             return parsed_value;

+ 1 - 0
Userland/Libraries/LibWeb/CSS/Parser/Parser.h

@@ -178,6 +178,7 @@ private:
     static RefPtr<StyleValue> parse_background_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
     static RefPtr<StyleValue> parse_box_shadow_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
     static RefPtr<StyleValue> parse_flex_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
+    static RefPtr<StyleValue> parse_flex_flow_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
     static RefPtr<StyleValue> parse_font_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
     static RefPtr<StyleValue> parse_list_style_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
     static RefPtr<StyleValue> parse_text_decoration_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);

+ 9 - 63
Userland/Libraries/LibWeb/CSS/StyleResolver.cpp

@@ -219,37 +219,6 @@ static inline bool is_color(StyleValue const& value)
     return false;
 }
 
-static inline bool is_flex_direction(StyleValue const& value)
-{
-    if (value.is_builtin_or_dynamic())
-        return true;
-
-    switch (value.to_identifier()) {
-    case ValueID::Row:
-    case ValueID::RowReverse:
-    case ValueID::Column:
-    case ValueID::ColumnReverse:
-        return true;
-    default:
-        return false;
-    }
-}
-
-static inline bool is_flex_wrap(StyleValue const& value)
-{
-    if (value.is_builtin_or_dynamic())
-        return true;
-
-    switch (value.to_identifier()) {
-    case ValueID::Wrap:
-    case ValueID::Nowrap:
-    case ValueID::WrapReverse:
-        return true;
-    default:
-        return false;
-    }
-}
-
 static inline bool is_font_family(StyleValue const& value)
 {
     if (value.is_builtin_or_dynamic())
@@ -793,40 +762,17 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
     }
 
     if (property_id == CSS::PropertyID::FlexFlow) {
-        if (value.is_component_value_list()) {
-            auto parts = static_cast<CSS::ValueListStyleValue const&>(value).values();
-            if (parts.is_empty() || parts.size() > 2)
-                return;
-
-            RefPtr<StyleValue> flex_direction_value;
-            RefPtr<StyleValue> flex_wrap_value;
-
-            for (auto& part : parts) {
-                auto value = Parser::parse_css_value(context, property_id, part);
-                if (!value)
-                    return;
-                if (is_flex_direction(*value)) {
-                    if (flex_direction_value)
-                        return;
-                    flex_direction_value = move(value);
-                    continue;
-                }
-                if (is_flex_wrap(*value)) {
-                    if (flex_wrap_value)
-                        return;
-                    flex_wrap_value = move(value);
-                    continue;
-                }
-            }
-
-            if (flex_direction_value)
-                style.set_property(CSS::PropertyID::FlexDirection, *flex_direction_value);
-            if (flex_wrap_value)
-                style.set_property(CSS::PropertyID::FlexWrap, *flex_wrap_value);
-
+        if (value.is_flex_flow()) {
+            auto& flex_flow = static_cast<FlexFlowStyleValue const&>(value);
+            style.set_property(CSS::PropertyID::FlexDirection, flex_flow.flex_direction());
+            style.set_property(CSS::PropertyID::FlexWrap, flex_flow.flex_wrap());
+            return;
+        }
+        if (value.is_builtin()) {
+            style.set_property(CSS::PropertyID::FlexDirection, value);
+            style.set_property(CSS::PropertyID::FlexWrap, value);
             return;
         }
-
         return;
     }
 

+ 30 - 0
Userland/Libraries/LibWeb/CSS/StyleValue.h

@@ -232,6 +232,7 @@ public:
         Background,
         BoxShadow,
         Flex,
+        FlexFlow,
         Font,
         ListStyle,
         TextDecoration,
@@ -254,6 +255,7 @@ public:
     bool is_background() const { return type() == Type::Background; }
     bool is_box_shadow() const { return type() == Type::BoxShadow; }
     bool is_flex() const { return type() == Type::Flex; }
+    bool is_flex_flow() const { return type() == Type::FlexFlow; }
     bool is_font() const { return type() == Type::Font; }
     bool is_list_style() const { return type() == Type::ListStyle; }
     bool is_text_decoration() const { return type() == Type::TextDecoration; }
@@ -716,6 +718,34 @@ private:
     NonnullRefPtr<StyleValue> m_basis;
 };
 
+class FlexFlowStyleValue final : public StyleValue {
+public:
+    static NonnullRefPtr<FlexFlowStyleValue> create(NonnullRefPtr<StyleValue> flex_direction, NonnullRefPtr<StyleValue> flex_wrap)
+    {
+        return adopt_ref(*new FlexFlowStyleValue(flex_direction, flex_wrap));
+    }
+    virtual ~FlexFlowStyleValue() override { }
+
+    NonnullRefPtr<StyleValue> flex_direction() const { return m_flex_direction; }
+    NonnullRefPtr<StyleValue> flex_wrap() const { return m_flex_wrap; }
+
+    virtual String to_string() const override
+    {
+        return String::formatted("FlexFlow flex_direction: {}, flex_wrap: {}", m_flex_direction->to_string(), m_flex_wrap->to_string());
+    }
+
+private:
+    FlexFlowStyleValue(NonnullRefPtr<StyleValue> flex_direction, NonnullRefPtr<StyleValue> flex_wrap)
+        : StyleValue(Type::FlexFlow)
+        , m_flex_direction(flex_direction)
+        , m_flex_wrap(flex_wrap)
+    {
+    }
+
+    NonnullRefPtr<StyleValue> m_flex_direction;
+    NonnullRefPtr<StyleValue> m_flex_wrap;
+};
+
 class FontStyleValue final : public StyleValue {
 public:
     static NonnullRefPtr<FontStyleValue> create(NonnullRefPtr<StyleValue> font_style, NonnullRefPtr<StyleValue> font_weight, NonnullRefPtr<StyleValue> font_size, NonnullRefPtr<StyleValue> line_height, NonnullRefPtrVector<StyleValue>&& font_families) { return adopt_ref(*new FontStyleValue(font_style, font_weight, font_size, line_height, move(font_families))); }