mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-22 17:31:58 -05:00
LibWeb: Create BlockContainer layout node for <input type="button">
...and shadow tree with TextNode for "value" attribute is created. This means InlineFormattingContext is used, and button's text now respects CSS text-decoration properties and unicode-ranges. (cherry picked from commit 8feaecd5c8d02a2fdb989a9a9671e008d1c3a7de)
This commit is contained in:
parent
7b47c57c54
commit
c6e3c0a339
11 changed files with 16 additions and 183 deletions
|
@ -12,7 +12,6 @@ source_set("Layout") {
|
|||
"Box.cpp",
|
||||
"BoxModelMetrics.cpp",
|
||||
"BreakNode.cpp",
|
||||
"ButtonBox.cpp",
|
||||
"CanvasBox.cpp",
|
||||
"CheckBox.cpp",
|
||||
"FlexFormattingContext.cpp",
|
||||
|
|
|
@ -12,7 +12,6 @@ source_set("Painting") {
|
|||
"BorderRadiiData.cpp",
|
||||
"BorderRadiusCornerClipper.cpp",
|
||||
"BordersData.cpp",
|
||||
"ButtonPaintable.cpp",
|
||||
"CanvasPaintable.cpp",
|
||||
"CheckBoxPaintable.cpp",
|
||||
"ClippableAndScrollable.cpp",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
wfh :^) PASS wfh :^) wfh :^) FAIL PASS FAIL wfh :^) FAIL FAIL PASS PASS wfh :^) wfh :^) PASS PASSwfh :^) FAIL wfh :^) FAIL wfh :^) wfh :^) FAIL wfh :^) wfh :^) defaultButton: click button=PASS
|
||||
wfh :^) PASS wfh :^) PASS wfh :^) FAIL PASS FAIL wfh :^) FAIL FAIL PASS PASS wfh :^) wfh :^) PASS PASSwfh :^) FAIL wfh :^) FAIL wfh :^) wfh :^) FAIL wfh :^) wfh :^) defaultButton: click button=PASS
|
||||
defaultButton: submit
|
||||
defaultButton: handledEvent=true
|
||||
defaultButtonAsInput: click button=PASS
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
pass Select file...No file selected. text: "pass"
|
||||
pass pass Select file...No file selected. text: "pass"
|
||||
hidden: "pass"
|
||||
button: "pass"
|
||||
checkbox: "pass"
|
||||
|
|
|
@ -470,7 +470,6 @@ set(SOURCES
|
|||
Layout/Box.cpp
|
||||
Layout/BoxModelMetrics.cpp
|
||||
Layout/BreakNode.cpp
|
||||
Layout/ButtonBox.cpp
|
||||
Layout/CanvasBox.cpp
|
||||
Layout/CheckBox.cpp
|
||||
Layout/FlexFormattingContext.cpp
|
||||
|
@ -536,7 +535,6 @@ set(SOURCES
|
|||
Painting/BorderPainting.cpp
|
||||
Painting/BorderRadiusCornerClipper.cpp
|
||||
Painting/BordersData.cpp
|
||||
Painting/ButtonPaintable.cpp
|
||||
Painting/CanvasPaintable.cpp
|
||||
Painting/Command.cpp
|
||||
Painting/CommandExecutorCPU.cpp
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
#include <LibWeb/Infra/CharacterTypes.h>
|
||||
#include <LibWeb/Infra/Strings.h>
|
||||
#include <LibWeb/Layout/BlockContainer.h>
|
||||
#include <LibWeb/Layout/ButtonBox.h>
|
||||
#include <LibWeb/Layout/CheckBox.h>
|
||||
#include <LibWeb/Layout/ImageBox.h>
|
||||
#include <LibWeb/Layout/RadioButton.h>
|
||||
|
@ -100,7 +99,7 @@ JS::GCPtr<Layout::Node> HTMLInputElement::create_layout_node(NonnullRefPtr<CSS::
|
|||
return nullptr;
|
||||
|
||||
if (type_state() == TypeAttributeState::SubmitButton || type_state() == TypeAttributeState::Button || type_state() == TypeAttributeState::ResetButton)
|
||||
return heap().allocate_without_realm<Layout::ButtonBox>(document(), *this, move(style));
|
||||
return heap().allocate_without_realm<Layout::BlockContainer>(document(), this, move(style));
|
||||
|
||||
if (type_state() == TypeAttributeState::ImageButton)
|
||||
return heap().allocate_without_realm<Layout::ImageBox>(document(), *this, move(style), *this);
|
||||
|
@ -740,9 +739,12 @@ void HTMLInputElement::create_shadow_tree_if_needed()
|
|||
case TypeAttributeState::Hidden:
|
||||
case TypeAttributeState::RadioButton:
|
||||
case TypeAttributeState::Checkbox:
|
||||
break;
|
||||
case TypeAttributeState::Button:
|
||||
case TypeAttributeState::SubmitButton:
|
||||
case TypeAttributeState::ResetButton:
|
||||
create_button_input_shadow_tree();
|
||||
break;
|
||||
case TypeAttributeState::ImageButton:
|
||||
break;
|
||||
case TypeAttributeState::Color:
|
||||
|
@ -779,6 +781,15 @@ void HTMLInputElement::update_shadow_tree()
|
|||
}
|
||||
}
|
||||
|
||||
void HTMLInputElement::create_button_input_shadow_tree()
|
||||
{
|
||||
auto shadow_root = heap().allocate<DOM::ShadowRoot>(realm(), document(), *this, Bindings::ShadowRootMode::Closed);
|
||||
set_shadow_root(shadow_root);
|
||||
|
||||
m_text_node = heap().allocate<DOM::Text>(realm(), document(), value());
|
||||
MUST(shadow_root->append_child(*m_text_node));
|
||||
}
|
||||
|
||||
void HTMLInputElement::create_text_input_shadow_tree()
|
||||
{
|
||||
auto shadow_root = heap().allocate<DOM::ShadowRoot>(realm(), document(), *this, Bindings::ShadowRootMode::Closed);
|
||||
|
|
|
@ -243,6 +243,7 @@ private:
|
|||
static TypeAttributeState parse_type_attribute(StringView);
|
||||
void create_shadow_tree_if_needed();
|
||||
void update_shadow_tree();
|
||||
void create_button_input_shadow_tree();
|
||||
void create_text_input_shadow_tree();
|
||||
void create_color_input_shadow_tree();
|
||||
void create_file_input_shadow_tree();
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibGfx/Font/Font.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/Layout/ButtonBox.h>
|
||||
#include <LibWeb/Painting/ButtonPaintable.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
JS_DEFINE_ALLOCATOR(ButtonBox);
|
||||
|
||||
ButtonBox::ButtonBox(DOM::Document& document, HTML::HTMLInputElement& element, NonnullRefPtr<CSS::StyleProperties> style)
|
||||
: FormAssociatedLabelableNode(document, element, move(style))
|
||||
{
|
||||
}
|
||||
|
||||
ButtonBox::~ButtonBox() = default;
|
||||
|
||||
void ButtonBox::prepare_for_replaced_layout()
|
||||
{
|
||||
// For <input type="submit" /> and <input type="button" />, the contents of
|
||||
// the button does not appear as the contents of the element but as the
|
||||
// value attribute. This is not the case with <button />, which contains
|
||||
// its contents normally.
|
||||
if (is<HTML::HTMLInputElement>(dom_node())) {
|
||||
set_natural_width(CSSPixels::nearest_value_for(first_available_font().width(static_cast<HTML::HTMLInputElement&>(dom_node()).value())));
|
||||
set_natural_height(first_available_font().pixel_size_rounded_up());
|
||||
}
|
||||
}
|
||||
|
||||
JS::GCPtr<Painting::Paintable> ButtonBox::create_paintable() const
|
||||
{
|
||||
return Painting::ButtonPaintable::create(*this);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/HTML/HTMLInputElement.h>
|
||||
#include <LibWeb/Layout/FormAssociatedLabelableNode.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
class ButtonBox final : public FormAssociatedLabelableNode {
|
||||
JS_CELL(ButtonBox, FormAssociatedLabelableNode);
|
||||
JS_DECLARE_ALLOCATOR(ButtonBox);
|
||||
|
||||
public:
|
||||
ButtonBox(DOM::Document&, HTML::HTMLInputElement&, NonnullRefPtr<CSS::StyleProperties>);
|
||||
virtual ~ButtonBox() override;
|
||||
|
||||
virtual void prepare_for_replaced_layout() override;
|
||||
|
||||
private:
|
||||
virtual JS::GCPtr<Painting::Paintable> create_paintable() const override;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/HTML/BrowsingContext.h>
|
||||
#include <LibWeb/HTML/HTMLImageElement.h>
|
||||
#include <LibWeb/Layout/ButtonBox.h>
|
||||
#include <LibWeb/Layout/Label.h>
|
||||
#include <LibWeb/Painting/ButtonPaintable.h>
|
||||
|
||||
namespace Web::Painting {
|
||||
|
||||
JS_DEFINE_ALLOCATOR(ButtonPaintable);
|
||||
|
||||
JS::NonnullGCPtr<ButtonPaintable> ButtonPaintable::create(Layout::ButtonBox const& layout_box)
|
||||
{
|
||||
return layout_box.heap().allocate_without_realm<ButtonPaintable>(layout_box);
|
||||
}
|
||||
|
||||
ButtonPaintable::ButtonPaintable(Layout::ButtonBox const& layout_box)
|
||||
: LabelablePaintable(layout_box)
|
||||
{
|
||||
}
|
||||
|
||||
Layout::ButtonBox const& ButtonPaintable::layout_box() const
|
||||
{
|
||||
return static_cast<Layout::ButtonBox const&>(layout_node());
|
||||
}
|
||||
|
||||
Layout::ButtonBox& ButtonPaintable::layout_box()
|
||||
{
|
||||
return static_cast<Layout::ButtonBox&>(layout_node());
|
||||
}
|
||||
|
||||
void ButtonPaintable::paint(PaintContext& context, PaintPhase phase) const
|
||||
{
|
||||
if (!is_visible())
|
||||
return;
|
||||
|
||||
PaintableBox::paint(context, phase);
|
||||
|
||||
auto const& dom_node = layout_box().dom_node();
|
||||
if (is<HTML::HTMLInputElement>(dom_node) && phase == PaintPhase::Foreground) {
|
||||
auto button_rect = context.enclosing_device_rect(absolute_rect());
|
||||
auto text_rect = button_rect;
|
||||
|
||||
// Apply CSS text-indent property to text rect
|
||||
// FIXME: The second parameter to to_px() needs to be the block container’s own inline-axis inner size:
|
||||
// https://drafts.csswg.org/css-text-3/#propdef-text-indent
|
||||
auto text_indent = computed_values().text_indent().to_px(layout_box(), CSSPixels());
|
||||
text_rect.translate_by(context.rounded_device_pixels(text_indent), 0);
|
||||
|
||||
// Apply button pressed state offset
|
||||
if (being_pressed()) {
|
||||
auto offset = context.rounded_device_pixels(1);
|
||||
text_rect.translate_by(offset, offset);
|
||||
}
|
||||
|
||||
// Paint button text clipped to button rect
|
||||
auto& painter = context.recording_painter();
|
||||
painter.save();
|
||||
auto clip_rect = absolute_rect();
|
||||
clip_rect.translate_by(enclosing_scroll_frame_offset().value_or({}));
|
||||
painter.add_clip_rect(context.enclosing_device_rect(clip_rect).to_type<int>());
|
||||
painter.draw_text(
|
||||
text_rect.to_type<int>(),
|
||||
static_cast<HTML::HTMLInputElement const&>(dom_node).value(),
|
||||
layout_box().scaled_font(context.device_pixels_per_css_pixel()),
|
||||
Gfx::TextAlignment::Center,
|
||||
computed_values().color());
|
||||
painter.restore();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/Layout/ButtonBox.h>
|
||||
#include <LibWeb/Painting/LabelablePaintable.h>
|
||||
|
||||
namespace Web::Painting {
|
||||
|
||||
class ButtonPaintable final : public LabelablePaintable {
|
||||
JS_CELL(ButtonPaintable, LabelablePaintable);
|
||||
JS_DECLARE_ALLOCATOR(ButtonPaintable);
|
||||
|
||||
public:
|
||||
static JS::NonnullGCPtr<ButtonPaintable> create(Layout::ButtonBox const&);
|
||||
|
||||
virtual void paint(PaintContext&, PaintPhase) const override;
|
||||
|
||||
Layout::ButtonBox const& layout_box() const;
|
||||
Layout::ButtonBox& layout_box();
|
||||
|
||||
private:
|
||||
ButtonPaintable(Layout::ButtonBox const&);
|
||||
};
|
||||
|
||||
}
|
Loading…
Reference in a new issue