2 * Copyright (C) 2005, 2006, 2007 Apple, Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "EditCommand.h"
29 #include "CompositeEditCommand.h"
30 #include "DeleteButtonController.h"
34 #include "EventNames.h"
36 #include "FrameSelection.h"
37 #include "ScopedEventQueue.h"
38 #include "VisiblePosition.h"
39 #include "htmlediting.h"
43 EditCommand::EditCommand(Document* document)
44 : m_document(document)
48 ASSERT(m_document->frame());
49 setStartingSelection(avoidIntersectionWithNode(m_document->frame()->selection()->selection(), m_document->frame()->editor()->deleteButtonController()->containerElement()));
50 setEndingSelection(m_startingSelection);
53 EditCommand::~EditCommand()
57 void EditCommand::apply()
60 ASSERT(m_document->frame());
62 Frame* frame = m_document->frame();
64 if (isTopLevelCommand()) {
65 if (!endingSelection().isContentRichlyEditable()) {
66 switch (editingAction()) {
67 case EditActionTyping:
70 case EditActionSetWritingDirection:
72 case EditActionUnspecified:
81 // Changes to the document may have been made since the last editing operation that
82 // require a layout, as in <rdar://problem/5658603>. Low level operations, like
83 // RemoveNodeCommand, don't require a layout because the high level operations that
84 // use them perform one if one is necessary (like for the creation of VisiblePositions).
85 if (isTopLevelCommand())
89 EventQueueScope scope;
90 DeleteButtonController* deleteButtonController = frame->editor()->deleteButtonController();
91 deleteButtonController->disable();
93 deleteButtonController->enable();
96 if (isTopLevelCommand()) {
97 // Only need to call appliedEditing for top-level commands, and TypingCommands do it on their
98 // own (see TypingCommand::typingAddedToOpenCommand).
99 if (!isTypingCommand())
100 frame->editor()->appliedEditing(this);
103 setShouldRetainAutocorrectionIndicator(false);
106 void EditCommand::unapply()
109 ASSERT(m_document->frame());
111 Frame* frame = m_document->frame();
113 // Changes to the document may have been made since the last editing operation that
114 // require a layout, as in <rdar://problem/5658603>. Low level operations, like
115 // RemoveNodeCommand, don't require a layout because the high level operations that
116 // use them perform one if one is necessary (like for the creation of VisiblePositions).
117 if (isTopLevelCommand())
120 DeleteButtonController* deleteButtonController = frame->editor()->deleteButtonController();
121 deleteButtonController->disable();
123 deleteButtonController->enable();
125 if (isTopLevelCommand())
126 frame->editor()->unappliedEditing(this);
129 void EditCommand::reapply()
132 ASSERT(m_document->frame());
134 Frame* frame = m_document->frame();
136 // Changes to the document may have been made since the last editing operation that
137 // require a layout, as in <rdar://problem/5658603>. Low level operations, like
138 // RemoveNodeCommand, don't require a layout because the high level operations that
139 // use them perform one if one is necessary (like for the creation of VisiblePositions).
140 if (isTopLevelCommand())
143 DeleteButtonController* deleteButtonController = frame->editor()->deleteButtonController();
144 deleteButtonController->disable();
146 deleteButtonController->enable();
148 if (isTopLevelCommand())
149 frame->editor()->reappliedEditing(this);
152 void EditCommand::doReapply()
157 EditAction EditCommand::editingAction() const
159 return EditActionUnspecified;
162 void EditCommand::setStartingSelection(const VisibleSelection& s)
164 Element* root = s.rootEditableElement();
165 for (EditCommand* cmd = this; ; cmd = cmd->m_parent) {
166 cmd->m_startingSelection = s;
167 cmd->m_startingRootEditableElement = root;
168 if (!cmd->m_parent || cmd->m_parent->isFirstCommand(cmd))
173 void EditCommand::setEndingSelection(const VisibleSelection &s)
175 Element* root = s.rootEditableElement();
176 for (EditCommand* cmd = this; cmd; cmd = cmd->m_parent) {
177 cmd->m_endingSelection = s;
178 cmd->m_endingRootEditableElement = root;
182 bool EditCommand::preservesTypingStyle() const
187 bool EditCommand::isTypingCommand() const
192 bool EditCommand::isCreateLinkCommand() const
197 bool EditCommand::shouldRetainAutocorrectionIndicator() const
202 void EditCommand::setShouldRetainAutocorrectionIndicator(bool)
206 void EditCommand::updateLayout() const
208 document()->updateLayoutIgnorePendingStylesheets();
211 void EditCommand::setParent(CompositeEditCommand* 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;
222 void applyCommand(PassRefPtr<EditCommand> command)
227 } // namespace WebCore