Changeset 102357 in webkit
- Timestamp:
- Dec 8, 2011 11:32:17 AM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r102356 r102357 1 2011-12-08 Ryosuke Niwa <rniwa@webkit.org> 2 3 CompositeEditCommand should not be kept alive for undo and redo 4 https://bugs.webkit.org/show_bug.cgi?id=64414 5 6 Reviewed by Enrica Casucci. 7 8 This patch introduces EditCommandComposition that replaces CompositeEditCommand for 9 undo and redo purposes. Furthermore, we now keep a list of commands instead of a tree of commands 10 to unapply and reapply edit commands that composes an undoable action. 11 12 Each top-level CompositeEditCommand holds a ref-pointer to EditCommandComposition, 13 and applyCommandToComposite adds new SimpleEditCommands to the list. 14 15 * editing/CompositeEditCommand.cpp: 16 (WebCore::EditCommandComposition::create): 17 (WebCore::EditCommandComposition::doApply): Never used. 18 (WebCore::EditCommandComposition::doUnapply): 19 (WebCore::EditCommandComposition::doReapply): 20 (WebCore::EditCommandComposition::append): 21 (WebCore::CompositeEditCommand::~CompositeEditCommand): Add an assertion to ensure we didn't create 22 a composition for CompositeEditCommands that have parents. 23 (WebCore::CompositeEditCommand::doUnapply): Never used. 24 (WebCore::CompositeEditCommand::doReapply): Never used. 25 (WebCore::CompositeEditCommand::ensureComposition): Creates and attaches a EditCommandComposition. 26 (WebCore::CompositeEditCommand::applyCommandToComposite): Append a SimpleEditCommand to the composition. 27 28 * editing/CompositeEditCommand.h: 29 (WebCore::EditCommandComposition::EditCommandComposition): 30 (WebCore::CompositeEditCommand::composition): 31 (WebCore::toEditCommandComposition): 32 (WebCore::toCompositeEditCommand): 33 34 * editing/DeleteButtonController.cpp: Wrap RemoveNodeCommand in RemoveTargetCommand since top level 35 commands are now required to be a CompositeEditCommand. 36 (WebCore::RemoveTargetCommand::create): 37 (WebCore::RemoveTargetCommand::RemoveTargetCommand): 38 (WebCore::RemoveTargetCommand::doApply): 39 (WebCore::DeleteButtonController::deleteTarget): 40 41 * editing/EditCommand.cpp: 42 (WebCore::EditCommand::EditCommand): New constructor; used by EditCommandComposition. 43 (WebCore::EditCommand::apply): Create a composition for a top-level command. 44 (WebCore::EditCommand::unapply): Since we clear m_parent of SimpleEditCommand as soon as they are 45 added to EditCommandComposition, we can't use isTopLevelCommand() to differentiate EditCommandComposition 46 from SimpleEditCommand. Use isEditCommandComposition() instead. 47 (WebCore::EditCommand::reapply): Ditto. 48 (WebCore::compositionIfPossible): 49 (WebCore::EditCommand::setStartingSelection): Update the starting selection of EditCommandComposition. 50 (WebCore::EditCommand::setEndingSelection): Ditto. 51 (WebCore::EditCommand::setParent): Accepts a null pointer in order to avoid keeping a stale pointer in 52 m_parent inside SimpleEditCommand when CompositeEditCommand goes away. 53 54 * editing/EditCommand.h: 55 (WebCore::EditCommand::isSimpleEditCommand): 56 (WebCore::EditCommand::isCompositeEditCommand): 57 (WebCore::EditCommand::isEditCommandComposition): 58 (WebCore::EditCommand::parent): 59 (WebCore::toSimpleEditCommand): 60 61 * editing/Editor.cpp: 62 (WebCore::Editor::appliedEditing): Register a EditCommandComposition, instead of a CompositeEditCommand 63 to the undo stack. 64 (WebCore::Editor::unappliedEditing): Unapplied or reapplied commands are now always EditCommandComposition. 65 (WebCore::Editor::reappliedEditing): 66 * editing/Editor.h: 67 1 68 2011-12-08 Stephen White <senorblanco@chromium.org> 2 69 -
trunk/Source/WebCore/editing/CompositeEditCommand.cpp
r99594 r102357 71 71 using namespace HTMLNames; 72 72 73 CompositeEditCommand::CompositeEditCommand(Document *document) 74 : EditCommand(document) 75 { 76 } 77 78 CompositeEditCommand::~CompositeEditCommand() 79 { 80 } 81 82 void CompositeEditCommand::doUnapply() 73 PassRefPtr<EditCommandComposition> EditCommandComposition::create(Document* document, 74 const VisibleSelection& startingSelection, const VisibleSelection endingSelection) 75 { 76 return adoptRef(new EditCommandComposition(document, startingSelection, endingSelection)); 77 } 78 79 void EditCommandComposition::doApply() 80 { 81 ASSERT_NOT_REACHED(); 82 } 83 84 void EditCommandComposition::doUnapply() 83 85 { 84 86 size_t size = m_commands.size(); … … 87 89 } 88 90 89 void CompositeEditCommand::doReapply()91 void EditCommandComposition::doReapply() 90 92 { 91 93 size_t size = m_commands.size(); … … 94 96 } 95 97 98 void EditCommandComposition::append(SimpleEditCommand* command) 99 { 100 m_commands.append(command); 101 } 102 103 CompositeEditCommand::CompositeEditCommand(Document *document) 104 : EditCommand(document) 105 { 106 } 107 108 CompositeEditCommand::~CompositeEditCommand() 109 { 110 ASSERT(isTopLevelCommand() || !m_composition); 111 } 112 113 void CompositeEditCommand::doUnapply() 114 { 115 ASSERT_NOT_REACHED(); 116 } 117 118 void CompositeEditCommand::doReapply() 119 { 120 ASSERT_NOT_REACHED(); 121 } 122 123 EditCommandComposition* CompositeEditCommand::ensureComposition() 124 { 125 CompositeEditCommand* command = this; 126 while (command && command->parent()) 127 command = command->parent(); 128 if (!command->m_composition) 129 command->m_composition = EditCommandComposition::create(document(), startingSelection(), endingSelection()); 130 return command->m_composition.get(); 131 } 132 96 133 // 97 134 // sugary-sweet convenience functions to help create and apply edit commands in composite commands 98 135 // 99 void CompositeEditCommand::applyCommandToComposite(PassRefPtr<EditCommand> cmd) 100 { 101 cmd->setParent(this); 102 cmd->apply(); 103 m_commands.append(cmd); 104 } 105 106 void CompositeEditCommand::applyCommandToComposite(PassRefPtr<CompositeEditCommand> command, const VisibleSelection& selection) 107 { 136 void CompositeEditCommand::applyCommandToComposite(PassRefPtr<EditCommand> prpCommand) 137 { 138 RefPtr<EditCommand> command = prpCommand; 139 command->setParent(this); 140 command->apply(); 141 if (command->isSimpleEditCommand()) { 142 command->setParent(0); 143 ensureComposition()->append(toSimpleEditCommand(command.get())); 144 } 145 m_commands.append(command.release()); 146 } 147 148 void CompositeEditCommand::applyCommandToComposite(PassRefPtr<CompositeEditCommand> prpCommand, const VisibleSelection& selection) 149 { 150 RefPtr<CompositeEditCommand> command = prpCommand; 108 151 command->setParent(this); 109 152 if (selection != command->endingSelection()) { … … 112 155 } 113 156 command->apply(); 114 m_commands.append(command); 157 if (command->isSimpleEditCommand()) { 158 command->setParent(0); 159 ensureComposition()->append(toSimpleEditCommand(command.get())); 160 } 161 m_commands.append(command.release()); 115 162 } 116 163 -
trunk/Source/WebCore/editing/CompositeEditCommand.h
r90933 r102357 38 38 class Text; 39 39 40 class EditCommandComposition : public EditCommand { 41 public: 42 static PassRefPtr<EditCommandComposition> create(Document*, const VisibleSelection&, const VisibleSelection); 43 44 virtual void doApply() OVERRIDE; 45 virtual void doUnapply() OVERRIDE; 46 virtual void doReapply() OVERRIDE; 47 void append(SimpleEditCommand*); 48 49 private: 50 EditCommandComposition(Document* document, const VisibleSelection& startingSelection, const VisibleSelection& endingSelection) 51 : EditCommand(document, startingSelection, endingSelection) 52 { } 53 virtual bool isEditCommandComposition() const OVERRIDE { return true; } 54 55 Vector<RefPtr<SimpleEditCommand> > m_commands; 56 }; 57 40 58 class CompositeEditCommand : public EditCommand { 41 59 public: … … 43 61 44 62 bool isFirstCommand(EditCommand* command) { return !m_commands.isEmpty() && m_commands.first() == command; } 63 EditCommandComposition* composition() { return m_composition.get(); } 64 EditCommandComposition* ensureComposition(); 45 65 46 66 protected: … … 125 145 virtual void doUnapply(); 126 146 virtual void doReapply(); 147 148 bool isCompositeEditCommand() const OVERRIDE { return true; } 149 150 RefPtr<EditCommandComposition> m_composition; 127 151 }; 152 153 inline EditCommandComposition* toEditCommandComposition(EditCommand* command) 154 { 155 ASSERT(command); 156 ASSERT(command->isEditCommandComposition()); 157 return static_cast<EditCommandComposition*>(command); 158 } 159 160 inline CompositeEditCommand* toCompositeEditCommand(EditCommand* command) 161 { 162 ASSERT(command); 163 ASSERT(command->isCompositeEditCommand()); 164 return static_cast<CompositeEditCommand*>(command); 165 } 128 166 129 167 } // namespace WebCore -
trunk/Source/WebCore/editing/DeleteButtonController.cpp
r101707 r102357 32 32 #include "CSSPropertyNames.h" 33 33 #include "CSSValueKeywords.h" 34 #include "CompositeEditCommand.h" 34 35 #include "DeleteButton.h" 35 36 #include "Document.h" … … 361 362 } 362 363 364 class RemoveTargetCommand : public CompositeEditCommand { 365 public: 366 static PassRefPtr<RemoveTargetCommand> create(Document* document, PassRefPtr<Node> target) 367 { 368 return adoptRef(new RemoveTargetCommand(document, target)); 369 } 370 371 private: 372 RemoveTargetCommand(Document* document, PassRefPtr<Node> target) 373 : CompositeEditCommand(document) 374 , m_target(target) 375 { } 376 377 void doApply() 378 { 379 removeNode(m_target); 380 } 381 382 private: 383 RefPtr<Node> m_target; 384 }; 385 363 386 void DeleteButtonController::deleteTarget() 364 387 { … … 366 389 return; 367 390 368 RefPtr<Node> element = m_target;369 391 hide(); 370 392 … … 372 394 // within the target, we unconditionally update the selection to be 373 395 // a caret where the target had been. 374 Position pos = positionInParentBeforeNode( element.get());375 applyCommand(Remove NodeCommand::create(element.release()));396 Position pos = positionInParentBeforeNode(m_target.get()); 397 applyCommand(RemoveTargetCommand::create(m_frame->document(), m_target)); 376 398 m_frame->selection()->setSelection(VisiblePosition(pos)); 377 399 } -
trunk/Source/WebCore/editing/EditCommand.cpp
r90933 r102357 41 41 namespace WebCore { 42 42 43 EditCommand::EditCommand(Document* document) 43 EditCommand::EditCommand(Document* document) 44 44 : m_document(document) 45 45 , m_parent(0) … … 51 51 } 52 52 53 EditCommand::EditCommand(Document* document, const VisibleSelection& startingSelection, const VisibleSelection& endingSelection) 54 : m_document(document) 55 , m_parent(0) 56 { 57 ASSERT(m_document); 58 ASSERT(m_document->frame()); 59 setStartingSelection(startingSelection); 60 setEndingSelection(endingSelection); 61 } 62 53 63 EditCommand::~EditCommand() 54 64 { … … 63 73 64 74 if (isTopLevelCommand()) { 75 ASSERT(isCompositeEditCommand()); 65 76 if (!endingSelection().isContentRichlyEditable()) { 66 77 switch (editingAction()) { … … 77 88 } 78 89 } 90 toCompositeEditCommand(this)->ensureComposition(); 79 91 } 80 92 … … 95 107 96 108 if (isTopLevelCommand()) { 109 ASSERT(isCompositeEditCommand()); 97 110 // Only need to call appliedEditing for top-level commands, and TypingCommands do it on their 98 111 // own (see TypingCommand::typingAddedToOpenCommand). 99 112 if (!isTypingCommand()) 100 frame->editor()->appliedEditing(t his);113 frame->editor()->appliedEditing(toCompositeEditCommand(this)); 101 114 } 102 115 … … 123 136 deleteButtonController->enable(); 124 137 125 if (is TopLevelCommand())126 frame->editor()->unappliedEditing(t his);138 if (isEditCommandComposition()) 139 frame->editor()->unappliedEditing(toEditCommandComposition(this)); 127 140 } 128 141 … … 146 159 deleteButtonController->enable(); 147 160 148 if (is TopLevelCommand())149 frame->editor()->reappliedEditing(t his);161 if (isEditCommandComposition()) 162 frame->editor()->reappliedEditing(toEditCommandComposition(this)); 150 163 } 151 164 … … 158 171 { 159 172 return EditActionUnspecified; 173 } 174 175 static inline EditCommandComposition* compositionIfPossible(EditCommand* command) 176 { 177 if (!command->isCompositeEditCommand()) 178 return 0; 179 return toCompositeEditCommand(command)->composition(); 160 180 } 161 181 … … 164 184 Element* root = s.rootEditableElement(); 165 185 for (EditCommand* cmd = this; ; cmd = cmd->m_parent) { 186 if (EditCommandComposition* composition = compositionIfPossible(cmd)) { 187 ASSERT(cmd->isTopLevelCommand()); 188 composition->m_startingSelection = s; 189 composition->m_startingRootEditableElement = root; 190 } 166 191 cmd->m_startingSelection = s; 167 192 cmd->m_startingRootEditableElement = root; … … 175 200 Element* root = s.rootEditableElement(); 176 201 for (EditCommand* cmd = this; cmd; cmd = cmd->m_parent) { 202 if (EditCommandComposition* composition = compositionIfPossible(cmd)) { 203 ASSERT(cmd->isTopLevelCommand()); 204 composition->m_endingSelection = s; 205 composition->m_endingRootEditableElement = root; 206 } 177 207 cmd->m_endingSelection = s; 178 208 cmd->m_endingRootEditableElement = root; … … 211 241 void EditCommand::setParent(CompositeEditCommand* parent) 212 242 { 213 ASSERT( parent);214 ASSERT(! m_parent);243 ASSERT((parent && !m_parent) || (!parent && m_parent)); 244 ASSERT(!parent || !isCompositeEditCommand() || !toCompositeEditCommand(this)->composition()); 215 245 m_parent = parent; 216 m_startingSelection = parent->m_endingSelection; 217 m_endingSelection = parent->m_endingSelection; 218 m_startingRootEditableElement = parent->m_endingRootEditableElement; 219 m_endingRootEditableElement = parent->m_endingRootEditableElement; 246 if (parent) { 247 m_startingSelection = parent->m_endingSelection; 248 m_endingSelection = parent->m_endingSelection; 249 m_startingRootEditableElement = parent->m_endingRootEditableElement; 250 m_endingRootEditableElement = parent->m_endingRootEditableElement; 251 } 220 252 } 221 253 -
trunk/Source/WebCore/editing/EditCommand.h
r90933 r102357 53 53 Element* startingRootEditableElement() const { return m_startingRootEditableElement.get(); } 54 54 Element* endingRootEditableElement() const { return m_endingRootEditableElement.get(); } 55 55 56 virtual bool isSimpleEditCommand() const { return false; } 57 virtual bool isCompositeEditCommand() const { return false; } 58 virtual bool isEditCommandComposition() const { return false; } 56 59 virtual bool isTypingCommand() const; 57 60 virtual bool isCreateLinkCommand() const; 58 61 59 62 virtual bool preservesTypingStyle() const; 60 63 … … 66 69 protected: 67 70 EditCommand(Document*); 71 EditCommand(Document*, const VisibleSelection&, const VisibleSelection&); 68 72 69 73 Document* document() const { return m_document.get(); } 74 CompositeEditCommand* parent() const { return m_parent; } 70 75 71 76 void setStartingSelection(const VisibleSelection&); … … 92 97 protected: 93 98 SimpleEditCommand(Document* document) : EditCommand(document) { } 99 private: 100 virtual bool isSimpleEditCommand() const OVERRIDE { return true; } 94 101 }; 102 103 inline SimpleEditCommand* toSimpleEditCommand(EditCommand* command) 104 { 105 ASSERT(command); 106 ASSERT(command->isSimpleEditCommand()); 107 return static_cast<SimpleEditCommand*>(command); 108 } 95 109 96 110 void applyCommand(PassRefPtr<EditCommand>); -
trunk/Source/WebCore/editing/Editor.cpp
r102328 r102357 866 866 } 867 867 868 void Editor::appliedEditing(PassRefPtr< EditCommand> cmd)868 void Editor::appliedEditing(PassRefPtr<CompositeEditCommand> cmd) 869 869 { 870 870 m_frame->document()->updateLayout(); … … 889 889 m_lastEditCommand = cmd; 890 890 if (client()) 891 client()->registerCommandForUndo( m_lastEditCommand);891 client()->registerCommandForUndo(toCompositeEditCommand(m_lastEditCommand.get())->ensureComposition()); 892 892 } 893 893 respondToChangedContents(newSelection); 894 894 } 895 895 896 void Editor::unappliedEditing(PassRefPtr<EditCommand > cmd)896 void Editor::unappliedEditing(PassRefPtr<EditCommandComposition> cmd) 897 897 { 898 898 m_frame->document()->updateLayout(); … … 910 910 } 911 911 912 void Editor::reappliedEditing(PassRefPtr<EditCommand > cmd)912 void Editor::reappliedEditing(PassRefPtr<EditCommandComposition> cmd) 913 913 { 914 914 m_frame->document()->updateLayout(); -
trunk/Source/WebCore/editing/Editor.h
r102307 r102357 49 49 class CSSStyleDeclaration; 50 50 class Clipboard; 51 class SpellingCorrectionController;51 class CompositeEditCommand; 52 52 class DeleteButtonController; 53 53 class EditCommand; 54 class EditCommandComposition; 54 55 class EditorClient; 55 56 class EditorInternalCommand; … … 61 62 class SimpleFontData; 62 63 class SpellChecker; 64 class SpellingCorrectionController; 63 65 class Text; 64 66 class TextCheckerClient; 67 class TextEvent; 65 68 struct TextCheckingResult; 66 class TextEvent;67 69 68 70 struct CompositionUnderline { … … 165 167 void applyParagraphStyleToSelection(CSSStyleDeclaration*, EditAction); 166 168 167 void appliedEditing(PassRefPtr< EditCommand>);168 void unappliedEditing(PassRefPtr<EditCommand >);169 void reappliedEditing(PassRefPtr<EditCommand >);169 void appliedEditing(PassRefPtr<CompositeEditCommand>); 170 void unappliedEditing(PassRefPtr<EditCommandComposition>); 171 void reappliedEditing(PassRefPtr<EditCommandComposition>); 170 172 void unappliedSpellCorrection(const VisibleSelection& selectionOfCorrected, const String& corrected, const String& correction); 171 173
Note: See TracChangeset
for help on using the changeset viewer.