diff --git a/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.cpp index 39711cf2d0..62abdd9f95 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.cpp @@ -1,10 +1,15 @@ /* * Copyright (c) 2020-2022, the SerenityOS developers. + * Copyright (c) 2022, MacDue * * SPDX-License-Identifier: BSD-2-Clause */ +#include +#include #include +#include +#include #include #include @@ -19,7 +24,29 @@ HTMLProgressElement::~HTMLProgressElement() = default; RefPtr HTMLProgressElement::create_layout_node(NonnullRefPtr style) { - return adopt_ref(*new Layout::Progress(document(), *this, move(style))); + RefPtr layout_node; + if (style->appearance().value_or(CSS::Appearance::Auto) == CSS::Appearance::None) { + layout_node = adopt_ref(*new Layout::BlockContainer(document(), this, move(style))); + layout_node->set_inline(true); + } else { + layout_node = adopt_ref(*new Layout::Progress(document(), *this, move(style))); + } + return layout_node; +} + +bool HTMLProgressElement::using_system_appearance() const +{ + if (layout_node()) + return is(*layout_node()); + return false; +} + +void HTMLProgressElement::progress_position_updated() +{ + if (using_system_appearance()) + layout_node()->set_needs_display(); + else + document().invalidate_layout(); } double HTMLProgressElement::value() const @@ -41,9 +68,7 @@ void HTMLProgressElement::set_value(double value) return; set_attribute(HTML::AttributeNames::value, String::number(value)); - - if (layout_node()) - layout_node()->set_needs_display(); + progress_position_updated(); } double HTMLProgressElement::max() const @@ -65,9 +90,7 @@ void HTMLProgressElement::set_max(double value) return; set_attribute(HTML::AttributeNames::max, String::number(value)); - - if (layout_node()) - layout_node()->set_needs_display(); + progress_position_updated(); } double HTMLProgressElement::position() const diff --git a/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h b/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h index 76540e23cc..f1af0fd1b6 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h @@ -31,7 +31,11 @@ public: // https://html.spec.whatwg.org/multipage/forms.html#category-label virtual bool is_labelable() const override { return true; } + bool using_system_appearance() const; + private: + void progress_position_updated(); + bool is_determinate() const { return has_attribute(HTML::AttributeNames::value); } }; diff --git a/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp b/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp index 46aab132fe..595030e9a3 100644 --- a/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp +++ b/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp @@ -1,6 +1,7 @@ /* * Copyright (c) 2018-2022, Andreas Kling * Copyright (c) 2022, Sam Atkins + * Copyright (c) 2022, MacDue * * SPDX-License-Identifier: BSD-2-Clause */ @@ -12,10 +13,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -253,6 +256,22 @@ void TreeBuilder::create_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& element.set_pseudo_element_node({}, CSS::Selector::PseudoElement::Marker, list_item_marker); layout_node->append_child(move(list_item_marker)); } + + if (is(dom_node)) { + auto& progress = static_cast(dom_node); + if (!progress.using_system_appearance()) { + auto bar_style = style_computer.compute_style(progress, CSS::Selector::PseudoElement::ProgressBar); + auto value_style = style_computer.compute_style(progress, CSS::Selector::PseudoElement::ProgressValue); + auto position = progress.position(); + value_style->set_property(CSS::PropertyID::Width, CSS::PercentageStyleValue::create(CSS::Percentage(position >= 0 ? round_to(100 * position) : 0))); + auto progress_bar = adopt_ref(*new Layout::BlockContainer(document, nullptr, bar_style)); + auto progress_value = adopt_ref(*new Layout::BlockContainer(document, nullptr, value_style)); + progress_bar->append_child(*progress_value); + layout_node->append_child(*progress_bar); + progress.set_pseudo_element_node({}, CSS::Selector::PseudoElement::ProgressBar, progress_bar); + progress.set_pseudo_element_node({}, CSS::Selector::PseudoElement::ProgressValue, progress_value); + } + } } RefPtr TreeBuilder::build(DOM::Node& dom_node)