diff options
author | asynts <asynts@gmail.com> | 2020-12-02 13:41:58 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-12-09 21:05:06 +0100 |
commit | e96faea1a232a349c4db31657624a577eaa6f7a0 (patch) | |
tree | 0c1ebef57c8c620db580365acda99ebbf9a6e59c | |
parent | 43dc47a4941d6aaa99ed847f879b4601094f6d4a (diff) | |
download | serenity-e96faea1a232a349c4db31657624a577eaa6f7a0.zip |
LibWeb: Support range delection accross nodes with shared parent.
-rw-r--r-- | Libraries/LibWeb/Page/EditEventHandler.cpp | 63 | ||||
-rw-r--r-- | Libraries/LibWeb/Page/EventHandler.cpp | 18 |
2 files changed, 56 insertions, 25 deletions
diff --git a/Libraries/LibWeb/Page/EditEventHandler.cpp b/Libraries/LibWeb/Page/EditEventHandler.cpp index de397ca220..20f8b7423c 100644 --- a/Libraries/LibWeb/Page/EditEventHandler.cpp +++ b/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) diff --git a/Libraries/LibWeb/Page/EventHandler.cpp b/Libraries/LibWeb/Page/EventHandler.cpp index 4a94a54c77..e8e806d57c 100644 --- a/Libraries/LibWeb/Page/EventHandler.cpp +++ b/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; |