summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEnver Balalic <balalic.enver@gmail.com>2022-03-31 22:11:38 +0200
committerAndreas Kling <kling@serenityos.org>2022-04-02 18:40:32 +0200
commit58398b1e127f1428261f4b86230c411573fb6426 (patch)
treeaeac1a6a98a80c64ce8f022ccd6f71ca301056fa
parent2377344a892b73258dbcb9ebe327e9356216f8bc (diff)
downloadserenity-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.html99
-rw-r--r--Base/res/html/misc/welcome.html1
-rw-r--r--Userland/Libraries/LibWeb/CSS/ComputedValues.h4
-rw-r--r--Userland/Libraries/LibWeb/CSS/Properties.json7
-rw-r--r--Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.cpp2
-rw-r--r--Userland/Libraries/LibWeb/CSS/StyleProperties.cpp8
-rw-r--r--Userland/Libraries/LibWeb/CSS/StyleProperties.h1
-rw-r--r--Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp20
-rw-r--r--Userland/Libraries/LibWeb/Layout/Node.cpp1
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())