diff options
author | asynts <asynts@gmail.com> | 2020-12-03 18:46:56 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-12-09 21:05:06 +0100 |
commit | a94a1d9f9eb9e75e9d1fc5365e7f27cc3172871d (patch) | |
tree | 67d27f170cb5bcf5326d8a78df58fe6712605321 /Libraries | |
parent | b3d7c5bfbca5b68246ff3459817872322d18951f (diff) | |
download | serenity-a94a1d9f9eb9e75e9d1fc5365e7f27cc3172871d.zip |
LibWeb: Implement deletion of more complex selections.
Diffstat (limited to 'Libraries')
-rw-r--r-- | Libraries/LibWeb/Page/EditEventHandler.cpp | 78 | ||||
-rw-r--r-- | Libraries/LibWeb/Page/EventHandler.cpp | 1 |
2 files changed, 42 insertions, 37 deletions
diff --git a/Libraries/LibWeb/Page/EditEventHandler.cpp b/Libraries/LibWeb/Page/EditEventHandler.cpp index 12a0e4cf4d..8a33ec6df2 100644 --- a/Libraries/LibWeb/Page/EditEventHandler.cpp +++ b/Libraries/LibWeb/Page/EditEventHandler.cpp @@ -40,45 +40,49 @@ namespace Web { void EditEventHandler::handle_delete(DOM::Range range) { - if (range.start().node() != range.end().node()) { - if (range.start().node()->parent() == range.end().node()->parent()) { - // Remove all intermediate nodes. - auto* current = range.start().node()->next_sibling(); - while (current != range.end().node()) { - auto* next = current->next_sibling(); - current->parent()->remove_child(*current); - current = next; - } - - // Join remaining text together. - StringBuilder builder; - builder.append(downcast<DOM::Text>(range.start().node())->data().substring_view(0, range.start().offset())); - builder.append(downcast<DOM::Text>(range.end().node())->data().substring_view(range.end().offset())); - - range.start().node()->parent()->remove_child(*range.end().node()); - downcast<DOM::Text>(range.start().node())->set_data(builder.to_string()); - - range.start().node()->invalidate_style(); - } else { - TODO(); - } - } else { - if (is<DOM::Text>(*range.start().node())) { - m_frame.document()->layout_node()->set_selection({}); + auto* start = downcast<DOM::Text>(range.start().node()); + auto* end = downcast<DOM::Text>(range.end().node()); + + // Remove all the nodes that are fully enclosed in the range. + HashTable<DOM::Node*> queued_for_deletion; + for (auto* node = start->next_in_pre_order(); node; node = node->next_in_pre_order()) { + if (node == end) + break; + + queued_for_deletion.set(node); + } + for (auto* parent = start->parent(); parent; parent = parent->parent()) + queued_for_deletion.remove(parent); + for (auto* parent = end->parent(); parent; parent = parent->parent()) + queued_for_deletion.remove(parent); + for (auto* node : queued_for_deletion) + node->parent()->remove_child(*node); + + if (start == end || start->next_sibling() == end) { + // If the start and end text nodes are now immediate siblings, merge the remainders into one. - auto& node = downcast<DOM::Text>(*range.start().node()); + StringBuilder builder; + builder.append(start->data().substring_view(0, range.start().offset())); + builder.append(end->data().substring_view(range.end().offset())); + + start->set_data(builder.to_string()); + start->invalidate_style(); - StringBuilder builder; - builder.append(node.data().substring_view(0, range.start().offset())); - builder.append(node.data().substring_view(range.end().offset())); - node.set_data(builder.to_string()); + if (start != end) + start->parent()->remove_child(*end); + } else { + // Otherwise, remove parts from both nodes. - node.invalidate_style(); - } + start->set_data(start->data().substring_view(0, range.start().offset())); + start->invalidate_style(); + + end->set_data(end->data().substring_view(range.end().offset())); + end->invalidate_style(); } - // FIXME: We need to remove stale layout nodes when nodes are removed from the DOM. Currently, - // this is the only way to get these to disappear. + // FIXME: When nodes are removed from the DOM, the associated layout nodes become stale and still + // remain in the layout tree. This has to be fixed, this just causes everything to be recomputed + // which really hurts performance. m_frame.document()->force_layout(); } @@ -96,9 +100,9 @@ void EditEventHandler::handle_insert(DOM::Position position, u32 code_point) node.invalidate_style(); } - // FIXME: We need to remove stale layout nodes when nodes are removed from the DOM. Currently, - // this is the only way to get these to disappear. + // FIXME: When nodes are removed from the DOM, the associated layout nodes become stale and still + // remain in the layout tree. This has to be fixed, this just causes everything to be recomputed + // which really hurts performance. m_frame.document()->force_layout(); } - } diff --git a/Libraries/LibWeb/Page/EventHandler.cpp b/Libraries/LibWeb/Page/EventHandler.cpp index 48fbb68454..9f3f80b697 100644 --- a/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Libraries/LibWeb/Page/EventHandler.cpp @@ -422,4 +422,5 @@ void EventHandler::set_mouse_event_tracking_layout_node(Layout::Node* layout_nod else m_mouse_event_tracking_layout_node = nullptr; } + } |