BlockContainer.cpp 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /*
  2. * Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibGfx/Painter.h>
  7. #include <LibWeb/Dump.h>
  8. #include <LibWeb/Layout/BlockContainer.h>
  9. #include <LibWeb/Layout/InitialContainingBlock.h>
  10. #include <LibWeb/Layout/InlineFormattingContext.h>
  11. #include <LibWeb/Layout/ReplacedBox.h>
  12. #include <LibWeb/Layout/TextNode.h>
  13. #include <LibWeb/Painting/Paintable.h>
  14. namespace Web::Layout {
  15. BlockContainer::BlockContainer(DOM::Document& document, DOM::Node* node, NonnullRefPtr<CSS::StyleProperties> style)
  16. : Box(document, node, move(style))
  17. {
  18. }
  19. BlockContainer::BlockContainer(DOM::Document& document, DOM::Node* node, CSS::ComputedValues computed_values)
  20. : Box(document, node, move(computed_values))
  21. {
  22. }
  23. BlockContainer::~BlockContainer()
  24. {
  25. }
  26. HitTestResult BlockContainer::hit_test(const Gfx::IntPoint& position, HitTestType type) const
  27. {
  28. if (!children_are_inline())
  29. return Box::hit_test(position, type);
  30. HitTestResult last_good_candidate;
  31. for (auto& line_box : paint_box()->line_boxes()) {
  32. for (auto& fragment : line_box.fragments()) {
  33. if (is<Box>(fragment.layout_node()) && verify_cast<Box>(fragment.layout_node()).paint_box()->stacking_context())
  34. continue;
  35. if (enclosing_int_rect(fragment.absolute_rect()).contains(position)) {
  36. if (is<BlockContainer>(fragment.layout_node()))
  37. return verify_cast<BlockContainer>(fragment.layout_node()).hit_test(position, type);
  38. return { fragment.layout_node(), fragment.text_index_at(position.x()) };
  39. }
  40. if (fragment.absolute_rect().top() <= position.y())
  41. last_good_candidate = { fragment.layout_node(), fragment.text_index_at(position.x()) };
  42. }
  43. }
  44. if (type == HitTestType::TextCursor && last_good_candidate.layout_node)
  45. return last_good_candidate;
  46. return { paint_box()->absolute_border_box_rect().contains(position.x(), position.y()) ? this : nullptr };
  47. }
  48. bool BlockContainer::is_scrollable() const
  49. {
  50. // FIXME: Support horizontal scroll as well (overflow-x)
  51. return computed_values().overflow_y() == CSS::Overflow::Scroll;
  52. }
  53. void BlockContainer::set_scroll_offset(const Gfx::FloatPoint& offset)
  54. {
  55. // FIXME: If there is horizontal and vertical scroll ignore only part of the new offset
  56. if (offset.y() < 0 || m_scroll_offset == offset)
  57. return;
  58. m_scroll_offset = offset;
  59. set_needs_display();
  60. }
  61. Painting::PaintableWithLines const* BlockContainer::paint_box() const
  62. {
  63. return static_cast<Painting::PaintableWithLines const*>(Box::paint_box());
  64. }
  65. RefPtr<Painting::Paintable> BlockContainer::create_paintable() const
  66. {
  67. return Painting::PaintableWithLines::create(*this);
  68. }
  69. }