Ver código fonte

LibWeb: Implement deletion of more complex selections.

asynts 4 anos atrás
pai
commit
a94a1d9f9e

+ 41 - 37
Libraries/LibWeb/Page/EditEventHandler.cpp

@@ -40,45 +40,49 @@ namespace Web {
 
 
 void EditEventHandler::handle_delete(DOM::Range range)
 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();
     m_frame.document()->force_layout();
 }
 }
 
 
@@ -96,9 +100,9 @@ void EditEventHandler::handle_insert(DOM::Position position, u32 code_point)
         node.invalidate_style();
         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();
     m_frame.document()->force_layout();
 }
 }
-
 }
 }

+ 1 - 0
Libraries/LibWeb/Page/EventHandler.cpp

@@ -422,4 +422,5 @@ void EventHandler::set_mouse_event_tracking_layout_node(Layout::Node* layout_nod
     else
     else
         m_mouse_event_tracking_layout_node = nullptr;
         m_mouse_event_tracking_layout_node = nullptr;
 }
 }
+
 }
 }