Bläddra i källkod

LibWeb: Support range delection accross nodes with shared parent.

asynts 4 år sedan
förälder
incheckning
e96faea1a2
2 ändrade filer med 56 tillägg och 25 borttagningar
  1. 49 14
      Libraries/LibWeb/Page/EditEventHandler.cpp
  2. 7 11
      Libraries/LibWeb/Page/EventHandler.cpp

+ 49 - 14
Libraries/LibWeb/Page/EditEventHandler.cpp

@@ -31,6 +31,7 @@
 #include <LibWeb/Page/Frame.h>
 
 #include <LibWeb/DOM/Document.h>
+#include <LibWeb/Dump.h>
 #include <LibWeb/Layout/InitialContainingBlockBox.h>
 
 #include "EditEventHandler.h"
@@ -39,21 +40,55 @@ namespace Web {
 
 void EditEventHandler::handle_delete(DOM::Range range)
 {
-    if (range.start().node() != range.end().node())
-        TODO();
-
-    if (is<DOM::Text>(*range.start().node())) {
-        auto& node = downcast<DOM::Text>(*range.start().node());
-
-        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());
-
-        m_frame.document()->layout_node()->set_selection({});
-        node.invalidate_style();
+    // FIXME: Find a better way of updating the selection and cursor position.
+
+    if (range.start().node() != range.end().node()) {
+        if (range.start().node()->parent() == range.end().node()->parent()) {
+            m_frame.document()->layout_node()->set_selection({});
+            m_frame.cursor_position().set_offset(range.start().offset());
+
+            // 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;
+            }
+
+            if (!is<DOM::Text>(*range.start().node()) || !is<DOM::Text>(*range.end().node()))
+                TODO();
+
+            // 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({});
+            m_frame.cursor_position().set_offset(range.start().offset());
+
+            auto& node = downcast<DOM::Text>(*range.start().node());
+
+            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());
+
+            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.
+    m_frame.document()->force_layout();
 }
 
 void EditEventHandler::handle_delete(DOM::Position position)

+ 7 - 11
Libraries/LibWeb/Page/EventHandler.cpp

@@ -353,25 +353,21 @@ bool EventHandler::handle_keydown(KeyCode key, unsigned modifiers, u32 code_poin
                 m_edit_event_handler->handle_delete(range);
                 return true;
             }
+        } else {
+            m_edit_event_handler->handle_delete(range);
+            m_edit_event_handler->handle_insert(m_frame.cursor_position(), code_point);
+            return true;
         }
-
-        // FIXME: Check if this code point is in the printable character range.
-
-        m_edit_event_handler->handle_delete(range);
-        m_edit_event_handler->handle_insert(m_frame.cursor_position(), code_point);
-        return true;
     }
 
     if (m_frame.cursor_position().is_valid() && m_frame.cursor_position().node()->is_editable()) {
         if (key == KeyCode::Key_Backspace) {
             m_edit_event_handler->handle_delete(m_frame.cursor_position());
             return true;
+        } else {
+            m_edit_event_handler->handle_insert(m_frame.cursor_position(), code_point);
+            return true;
         }
-
-        // FIXME: Check if this code point is in the printable character range.
-
-        m_edit_event_handler->handle_insert(m_frame.cursor_position(), code_point);
-        return true;
     }
 
     return false;