1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 13:27:35 +00:00

LibWeb: Implement and use FlexFlowStyleValue

This commit is contained in:
Sam Atkins 2021-08-05 17:19:29 +01:00 committed by Andreas Kling
parent ab57d7b408
commit c27f99fc1d
4 changed files with 101 additions and 63 deletions

View file

@ -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;

View file

@ -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&);

View file

@ -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;
}

View file

@ -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))); }