diff options
author | Enver Balalic <balalic.enver@gmail.com> | 2022-03-31 22:11:38 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-04-02 18:40:32 +0200 |
commit | 58398b1e127f1428261f4b86230c411573fb6426 (patch) | |
tree | aeac1a6a98a80c64ce8f022ccd6f71ca301056fa | |
parent | 2377344a892b73258dbcb9ebe327e9356216f8bc (diff) | |
download | serenity-58398b1e127f1428261f4b86230c411573fb6426.zip |
LibWeb: Implement the flex order CSS property
Adds support for the flex order property and a test page for it
on the browser welcome page.
-rw-r--r-- | Base/res/html/misc/flex-order.html | 99 | ||||
-rw-r--r-- | Base/res/html/misc/welcome.html | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/ComputedValues.h | 4 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Properties.json | 7 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.cpp | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/StyleProperties.cpp | 8 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/StyleProperties.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp | 20 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Layout/Node.cpp | 1 |
9 files changed, 142 insertions, 1 deletions
diff --git a/Base/res/html/misc/flex-order.html b/Base/res/html/misc/flex-order.html new file mode 100644 index 0000000000..c0f328934e --- /dev/null +++ b/Base/res/html/misc/flex-order.html @@ -0,0 +1,99 @@ +<!DOCTYPE html> +<html> + +<head> + <title>Flex</title> + <style> + .my-container { + display: flex; + border: 1px solid salmon; + } + + .box { + width: 100px; + height: 100px; + border: 1px solid black; + } + + .inline { + display: inline-block + } + </style> +</head> + +<body> +<p>2/0/1</p> +<div class="my-container" style="width: 500px;"> + <div class="box" style="order: 2;flex: 80% 0 4;">1</div> + <div class="box" style="order: 0;flex: 80% 0 1;">2</div> + <div class="box" style="order: 1;flex: 80% 0 0;">3</div> +</div> +<p>2/0/1 - reverse</p> +<div class="my-container" style="flex-direction: row-reverse; width: 500px;"> + <div class="box" style="order: 2;flex: 80% 0 4;">1</div> + <div class="box" style="order: 0;flex: 80% 0 1;">2</div> + <div class="box" style="order: 1;flex: 80% 0 0;">3</div> +</div> +<p>2/<>/1</p> +<div class="my-container" style="width: 500px;"> + <div class="box" style="order: 2;flex: 80% 0 4;">1</div> + <div class="box" style="flex: 80% 0 1;">2</div> + <div class="box" style="order: 1;flex: 80% 0 0;">3</div> +</div> +<p>2/<>/1 - reverse</p> +<div class="my-container" style="flex-direction: row-reverse; width: 500px;"> + <div class="box" style="order: 2;flex: 80% 0 4;">1</div> + <div class="box" style="flex: 80% 0 1;">2</div> + <div class="box" style="order: 1;flex: 80% 0 0;">3</div> +</div> +<p>2/0/<></p> +<div class="my-container" style="width: 500px;"> + <div class="box" style="order: 2;flex: 80% 0 4;">1</div> + <div class="box" style="order: 0;flex: 80% 0 1;">2</div> + <div class="box" style="flex: 80% 0 0;">3</div> +</div> +<p><>/0/1</p> +<div class="my-container" style="width: 500px;"> + <div class="box" style="flex: 80% 0 4;">1</div> + <div class="box" style="order: 0;flex: 80% 0 1;">2</div> + <div class="box" style="order: 1;flex: 80% 0 0;">3</div> +</div> +<p><>/1/<></p> +<div class="my-container" style="width: 500px;"> + <div class="box" style="flex: 80% 0 4;">1</div> + <div class="box" style="order: 1;flex: 80% 0 1;">2</div> + <div class="box" style="flex: 80% 0 0;">3</div> +</div> +<p><>/0/<></p> +<div class="my-container" style="width: 500px;"> + <div class="box" style="flex: 80% 0 4;">1</div> + <div class="box" style="order: 0;flex: 80% 0 1;">2</div> + <div class="box" style="flex: 80% 0 0;">3</div> +</div> +<p>1/1/<></p> +<div class="my-container" style="width: 500px;"> + <div class="box" style="order: 1;flex: 80% 0 4;">1</div> + <div class="box" style="order: 1;flex: 80% 0 1;">2</div> + <div class="box" style="flex: 80% 0 0;">3</div> +</div> +<p>3/-1/-2</p> +<div class="my-container" style="width: 500px;"> + <div class="box" style="order: 3;flex: 80% 0 4;">1</div> + <div class="box" style="order: -1;flex: 80% 0 1;">2</div> + <div class="box" style="order: -2;flex: 80% 0 0;">3</div> +</div> +<p>-2/3/<></p> +<div class="my-container" style="width: 500px;"> + <div class="box" style="order: -2;flex: 80% 0 4;">1</div> + <div class="box" style="order: 3;flex: 80% 0 1;">2</div> + <div class="box" style="flex: 80% 0 0;">3</div> +</div> +<p><>/-1/<></p> +<div class="my-container" style="width: 500px;"> + <div class="box" style="flex: 80% 0 4;">1</div> + <div class="box" style="order: -1;flex: 80% 0 1;">2</div> + <div class="box" style="flex: 80% 0 0;">3</div> +</div> +</body> + +</html> diff --git a/Base/res/html/misc/welcome.html b/Base/res/html/misc/welcome.html index 318093c6b7..c2bc0319e0 100644 --- a/Base/res/html/misc/welcome.html +++ b/Base/res/html/misc/welcome.html @@ -117,6 +117,7 @@ <li><a href="border-radius.html">Border-Radius</a></li> <li><a href="lists.html">Lists</a></li> <li><a href="flex.html">Flexboxes</a></li> + <li><a href="flex-order.html">Flexbox order</a></li> <li><a href="justify-content.html">Flexbox justify-content</a></li> <li><a href="flex-2.html">Flexboxes with unusual children</a></li> <li><a href="inline-block.html">display: inline-block;</a></li> diff --git a/Userland/Libraries/LibWeb/CSS/ComputedValues.h b/Userland/Libraries/LibWeb/CSS/ComputedValues.h index 3462c152bd..c8b14a3f82 100644 --- a/Userland/Libraries/LibWeb/CSS/ComputedValues.h +++ b/Userland/Libraries/LibWeb/CSS/ComputedValues.h @@ -43,6 +43,7 @@ public: static CSS::PointerEvents pointer_events() { return CSS::PointerEvents::Auto; } static float flex_grow() { return 0.0f; } static float flex_shrink() { return 1.0f; } + static int order() { return 0; } static float opacity() { return 1.0f; } static CSS::Length border_radius() { return Length::make_px(0); } static Variant<CSS::VerticalAlign, CSS::LengthPercentage> vertical_align() { return CSS::VerticalAlign::Baseline; } @@ -133,6 +134,7 @@ public: FlexBasisData const& flex_basis() const { return m_noninherited.flex_basis; } float flex_grow() const { return m_noninherited.flex_grow; } float flex_shrink() const { return m_noninherited.flex_shrink; } + int order() const { return m_noninherited.order; } CSS::AlignItems align_items() const { return m_noninherited.align_items; } float opacity() const { return m_noninherited.opacity; } CSS::Visibility visibility() const { return m_inherited.visibility; } @@ -245,6 +247,7 @@ protected: CSS::FlexBasisData flex_basis {}; float flex_grow { InitialValues::flex_grow() }; float flex_shrink { InitialValues::flex_shrink() }; + int order { InitialValues::order() }; CSS::AlignItems align_items { InitialValues::align_items() }; CSS::JustifyContent justify_content { InitialValues::justify_content() }; CSS::Overflow overflow_x { InitialValues::overflow() }; @@ -313,6 +316,7 @@ public: void set_flex_basis(FlexBasisData value) { m_noninherited.flex_basis = value; } void set_flex_grow(float value) { m_noninherited.flex_grow = value; } void set_flex_shrink(float value) { m_noninherited.flex_shrink = value; } + void set_order(int value) { m_noninherited.order = value; } void set_align_items(CSS::AlignItems value) { m_noninherited.align_items = value; } void set_opacity(float value) { m_noninherited.opacity = value; } void set_justify_content(CSS::JustifyContent value) { m_noninherited.justify_content = value; } diff --git a/Userland/Libraries/LibWeb/CSS/Properties.json b/Userland/Libraries/LibWeb/CSS/Properties.json index d1021be84d..b225423ab9 100644 --- a/Userland/Libraries/LibWeb/CSS/Properties.json +++ b/Userland/Libraries/LibWeb/CSS/Properties.json @@ -689,6 +689,13 @@ "number" ] }, + "order": { + "inherited": false, + "initial": "0", + "valid-types": [ + "integer" + ] + }, "flex-wrap": { "inherited": false, "initial": "nowrap", diff --git a/Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.cpp b/Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.cpp index bd39948335..7f61cf1136 100644 --- a/Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.cpp +++ b/Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.cpp @@ -549,6 +549,8 @@ RefPtr<StyleValue> ResolvedCSSStyleDeclaration::style_value_for_property(Layout: return NumericStyleValue::create_float(layout_node.computed_values().flex_grow()); case CSS::PropertyID::FlexShrink: return NumericStyleValue::create_float(layout_node.computed_values().flex_shrink()); + case CSS::PropertyID::Order: + return NumericStyleValue::create_integer(layout_node.computed_values().order()); case CSS::PropertyID::Opacity: return NumericStyleValue::create_float(layout_node.computed_values().opacity()); case CSS::PropertyID::ImageRendering: diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp index 9856396e74..65af34895d 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp @@ -263,6 +263,14 @@ float StyleProperties::flex_shrink() const return value.value()->to_number(); } +int StyleProperties::order() const +{ + auto value = property(CSS::PropertyID::Order); + if (!value.has_value() || !value.value()->has_integer()) + return 0; + return value.value()->to_integer(); +} + Optional<CSS::ImageRendering> StyleProperties::image_rendering() const { auto value = property(CSS::PropertyID::ImageRendering); diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.h b/Userland/Libraries/LibWeb/CSS/StyleProperties.h index ef34a95e1b..3383d25a87 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleProperties.h +++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.h @@ -65,6 +65,7 @@ public: Optional<CSS::FlexBasisData> flex_basis() const; float flex_grow() const; float flex_shrink() const; + int order() const; Optional<CSS::AlignItems> align_items() const; float opacity() const; Optional<CSS::Visibility> visibility() const; diff --git a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp index fa7c21f1b6..74ce0b9afc 100644 --- a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp @@ -7,6 +7,7 @@ #include "InlineFormattingContext.h" #include <AK/Function.h> +#include <AK/QuickSort.h> #include <AK/StdLibExtras.h> #include <LibWeb/Layout/BlockContainer.h> #include <LibWeb/Layout/BlockFormattingContext.h> @@ -170,6 +171,8 @@ void FlexFormattingContext::generate_anonymous_flex_items() // calculations that could change that. // This is particularly important since we take references to the items stored in flex_items // later, whose addresses won't be stable if we added or removed any items. + HashMap<int, Vector<FlexItem>> order_item_bucket; + flex_container().for_each_child_of_type<Box>([&](Box& child_box) { // Skip anonymous text runs that are only whitespace. if (child_box.is_anonymous() && !child_box.first_child_of_type<BlockContainer>()) { @@ -192,9 +195,24 @@ void FlexFormattingContext::generate_anonymous_flex_items() child_box.set_flex_item(true); FlexItem flex_item = { child_box }; populate_specified_margins(flex_item, m_flex_direction); - m_flex_items.append(move(flex_item)); + + auto& order_bucket = order_item_bucket.ensure(child_box.computed_values().order()); + order_bucket.append(move(flex_item)); + return IterationDecision::Continue; }); + + auto keys = order_item_bucket.keys(); + quick_sort(keys, [](auto& a, auto& b) { return a < b; }); + + for (auto key : keys) { + auto order_bucket = order_item_bucket.get(key); + if (order_bucket.has_value()) { + for (auto flex_item : order_bucket.value()) { + m_flex_items.append(move(flex_item)); + } + } + } } bool FlexFormattingContext::has_definite_main_size(Box const& box) const diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp index 99803a25b0..60ee9ca2d5 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.cpp +++ b/Userland/Libraries/LibWeb/Layout/Node.cpp @@ -401,6 +401,7 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style) computed_values.set_flex_grow(computed_style.flex_grow()); computed_values.set_flex_shrink(computed_style.flex_shrink()); + computed_values.set_order(computed_style.order()); auto justify_content = computed_style.justify_content(); if (justify_content.has_value()) |