diff options
author | MacDue <macdue@dueutil.tech> | 2022-07-22 16:08:03 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-07-23 01:45:49 +0200 |
commit | 57c67924586ea71e86b9af3d883a07a1ec832480 (patch) | |
tree | 3057ca5f8748924f85449caef003118053e66b11 /Userland/Libraries | |
parent | d7d34d88e58321fbcdc79e005ab065086f01884d (diff) | |
download | serenity-57c67924586ea71e86b9af3d883a07a1ec832480.zip |
LibWeb: Support `appearance: none` for `<progress>` elements
This disables this system progress bar, and instead creates one
out of pseudo elements, that can be selected and styled with the
::-webkit-progress-bar/value selectors.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/HTMLProgressElement.cpp | 37 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h | 4 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp | 19 |
3 files changed, 53 insertions, 7 deletions
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 <macdue@dueutil.tech> * * SPDX-License-Identifier: BSD-2-Clause */ +#include <LibWeb/DOM/Document.h> +#include <LibWeb/DOM/ShadowRoot.h> #include <LibWeb/HTML/HTMLProgressElement.h> +#include <LibWeb/Layout/BlockContainer.h> +#include <LibWeb/Layout/Node.h> #include <LibWeb/Layout/Progress.h> #include <stdlib.h> @@ -19,7 +24,29 @@ HTMLProgressElement::~HTMLProgressElement() = default; RefPtr<Layout::Node> HTMLProgressElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style) { - return adopt_ref(*new Layout::Progress(document(), *this, move(style))); + RefPtr<Layout::Node> 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::Progress>(*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 <kling@serenityos.org> * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org> + * Copyright (c) 2022, MacDue <macdue@dueutil.tech> * * SPDX-License-Identifier: BSD-2-Clause */ @@ -12,10 +13,12 @@ #include <LibWeb/DOM/ParentNode.h> #include <LibWeb/DOM/ShadowRoot.h> #include <LibWeb/Dump.h> +#include <LibWeb/HTML/HTMLProgressElement.h> #include <LibWeb/Layout/InitialContainingBlock.h> #include <LibWeb/Layout/ListItemBox.h> #include <LibWeb/Layout/ListItemMarkerBox.h> #include <LibWeb/Layout/Node.h> +#include <LibWeb/Layout/Progress.h> #include <LibWeb/Layout/TableBox.h> #include <LibWeb/Layout/TableCellBox.h> #include <LibWeb/Layout/TableRowBox.h> @@ -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<HTML::HTMLProgressElement>(dom_node)) { + auto& progress = static_cast<HTML::HTMLProgressElement&>(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<int>(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<Node> TreeBuilder::build(DOM::Node& dom_node) |