HtmlView.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #include <LibGUI/GPainter.h>
  2. #include <LibGUI/GScrollBar.h>
  3. #include <LibHTML/DOM/Element.h>
  4. #include <LibHTML/DOM/HTMLAnchorElement.h>
  5. #include <LibHTML/Dump.h>
  6. #include <LibHTML/HtmlView.h>
  7. #include <LibHTML/Layout/LayoutNode.h>
  8. #include <LibHTML/RenderingContext.h>
  9. #include <stdio.h>
  10. HtmlView::HtmlView(GWidget* parent)
  11. : GScrollableWidget(parent)
  12. {
  13. set_frame_shape(FrameShape::Container);
  14. set_frame_shadow(FrameShadow::Sunken);
  15. set_frame_thickness(2);
  16. set_should_hide_unnecessary_scrollbars(true);
  17. set_background_color(Color::White);
  18. }
  19. void HtmlView::set_document(Document* document)
  20. {
  21. if (document == m_document)
  22. return;
  23. m_document = document;
  24. if (document == nullptr)
  25. m_layout_root = nullptr;
  26. else
  27. m_layout_root = document->create_layout_tree(document->style_resolver(), nullptr);
  28. #ifdef HTML_DEBUG
  29. if (document != nullptr) {
  30. printf("\033[33;1mLayout tree before layout:\033[0m\n");
  31. ::dump_tree(*m_layout_root);
  32. }
  33. #endif
  34. layout_and_sync_size();
  35. update();
  36. }
  37. void HtmlView::layout_and_sync_size()
  38. {
  39. if (!m_layout_root)
  40. return;
  41. m_layout_root->style().size().set_width(available_size().width());
  42. m_layout_root->layout();
  43. set_content_size(m_layout_root->rect().size());
  44. #ifdef HTML_DEBUG
  45. printf("\033[33;1mLayout tree after layout:\033[0m\n");
  46. ::dump_tree(*m_layout_root);
  47. #endif
  48. }
  49. void HtmlView::resize_event(GResizeEvent& event)
  50. {
  51. GScrollableWidget::resize_event(event);
  52. layout_and_sync_size();
  53. }
  54. void HtmlView::paint_event(GPaintEvent& event)
  55. {
  56. GFrame::paint_event(event);
  57. GPainter painter(*this);
  58. painter.add_clip_rect(widget_inner_rect());
  59. painter.add_clip_rect(event.rect());
  60. painter.fill_rect(event.rect(), background_color());
  61. painter.translate(frame_thickness(), frame_thickness());
  62. painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value());
  63. if (!m_layout_root)
  64. return;
  65. RenderingContext context { painter };
  66. m_layout_root->render(context);
  67. }
  68. void HtmlView::mousemove_event(GMouseEvent& event)
  69. {
  70. if (!m_layout_root)
  71. return GScrollableWidget::mousemove_event(event);
  72. bool hovered_node_changed = false;
  73. auto result = m_layout_root->hit_test(event.position());
  74. if (result.layout_node) {
  75. auto* node = result.layout_node->node();
  76. m_document->set_hovered_node(const_cast<Node*>(node));
  77. hovered_node_changed = node == m_document->hovered_node();
  78. if (node) {
  79. dbg() << "HtmlView: mousemove: " << node->tag_name() << "{" << node << "}";
  80. if (auto* link = node->enclosing_link_element()) {
  81. dbg() << "HtmlView: hovering over a link to " << link->href();
  82. }
  83. }
  84. }
  85. if (hovered_node_changed)
  86. update();
  87. event.accept();
  88. }
  89. void HtmlView::mousedown_event(GMouseEvent& event)
  90. {
  91. if (!m_layout_root)
  92. return GScrollableWidget::mousemove_event(event);
  93. bool hovered_node_changed = false;
  94. auto result = m_layout_root->hit_test(event.position());
  95. if (result.layout_node) {
  96. auto* node = result.layout_node->node();
  97. m_document->set_hovered_node(const_cast<Node*>(node));
  98. hovered_node_changed = node == m_document->hovered_node();
  99. if (node) {
  100. dbg() << "HtmlView: mousedown: " << node->tag_name() << "{" << node << "}";
  101. if (auto* link = node->enclosing_link_element()) {
  102. dbg() << "HtmlView: clicking on a link to " << link->href();
  103. if (on_link_click)
  104. on_link_click(link->href());
  105. }
  106. }
  107. }
  108. if (hovered_node_changed)
  109. update();
  110. event.accept();
  111. }