- fix http://bugs.webkit.org/show_bug.cgi?id=11379
assertion failure seen in editing tests (in new DeleteButtonController)
I cleaned up the relationship between the Frame, Editor, EditorClient, and
DeleteButtonController a bit while also making the simple change to fix the
assertion failure.
* bridge/mac/FrameMac.h: Change EditorClient parameter to a PassRefPtr since we take ownership.
* bridge/mac/FrameMac.mm: (WebCore::FrameMac::FrameMac):
* page/Frame.h: Change EditorClient parameter to a PassRefPtr since we take ownership.
* page/Frame.cpp:
(WebCore::Frame::Frame): Ditto.
(WebCore::Frame::appliedEditing): Removed unneeded parameter to the respondToChangedContents
function, and moved it to Editor rather than right on the DeleteButtonController.
(WebCore::Frame::unappliedEditing): Ditto.
(WebCore::Frame::reappliedEditing): Ditto.
* page/FramePrivate.h: (WebCore::FramePrivate::FramePrivate): More of the same.
* editing/DeleteButtonController.h:
* editing/DeleteButtonController.cpp:
(WebCore::DeleteButtonController::DeleteButtonController): Replaced Editor* with a Frame*.
The general pattern is that we always use the Frame* as the frame identifier. See FrameTree,
for example.
(WebCore::enclosingDeletableTable): Added. Helper function used by the respondToChangedSelection
function. Includes an additional check for whether the container is contentEditable, which
was missing from the old version. This prevents the assertion failure. Also added a check that
the table itself is editable.
(WebCore::DeleteButtonController::respondToChangedSelection): Rewrote to use the helper.
(WebCore::DeleteButtonController::respondToChangedContents): Removed the unnecessary
selection parameter. No need to pass in the state of the frame since we can get it if we need it.
(WebCore::DeleteButtonController::show): Updated to use frame pointer rather than editor pointer.
* editing/Editor.cpp: Fixed formatting. Even the temporary placeholder functions should be
formatted on multiple lines as usual.
(WebCore::Editor::respondToChangedSelection): Added. Forwards to the delete button controller.
(WebCore::Editor::respondToChangedContents): Ditto.
(WebCore::Editor::Editor): Changed EditorClient parameter to a PassRefPtr since we take ownership.
* editing/Editor.h: Changed the DeleteButtonController to use an OwnPtr instead of being
defined inline to decouple so that we don't have to include DeleteButtonController.h. That way
changes to DeleteButtonController.h cause very little to recompile.
* editing/SelectionController.cpp: (WebCore::SelectionController::setSelection):
Updated to call the editor instead of the delete button controller for the selection change.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@17202
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2006-10-21 Darin Adler <darin@apple.com>
+
+ Reviewed by Anders.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=11379
+ assertion failure seen in editing tests (in new DeleteButtonController)
+
+ I cleaned up the relationship between the Frame, Editor, EditorClient, and
+ DeleteButtonController a bit while also making the simple change to fix the
+ assertion failure.
+
+ * bridge/mac/FrameMac.h: Change EditorClient parameter to a PassRefPtr since we take ownership.
+ * bridge/mac/FrameMac.mm: (WebCore::FrameMac::FrameMac):
+
+ * page/Frame.h: Change EditorClient parameter to a PassRefPtr since we take ownership.
+ * page/Frame.cpp:
+ (WebCore::Frame::Frame): Ditto.
+ (WebCore::Frame::appliedEditing): Removed unneeded parameter to the respondToChangedContents
+ function, and moved it to Editor rather than right on the DeleteButtonController.
+ (WebCore::Frame::unappliedEditing): Ditto.
+ (WebCore::Frame::reappliedEditing): Ditto.
+ * page/FramePrivate.h: (WebCore::FramePrivate::FramePrivate): More of the same.
+
+ * editing/DeleteButtonController.h:
+ * editing/DeleteButtonController.cpp:
+ (WebCore::DeleteButtonController::DeleteButtonController): Replaced Editor* with a Frame*.
+ The general pattern is that we always use the Frame* as the frame identifier. See FrameTree,
+ for example.
+ (WebCore::enclosingDeletableTable): Added. Helper function used by the respondToChangedSelection
+ function. Includes an additional check for whether the container is contentEditable, which
+ was missing from the old version. This prevents the assertion failure. Also added a check that
+ the table itself is editable.
+ (WebCore::DeleteButtonController::respondToChangedSelection): Rewrote to use the helper.
+ (WebCore::DeleteButtonController::respondToChangedContents): Removed the unnecessary
+ selection parameter. No need to pass in the state of the frame since we can get it if we need it.
+ (WebCore::DeleteButtonController::show): Updated to use frame pointer rather than editor pointer.
+
+ * editing/Editor.cpp: Fixed formatting. Even the temporary placeholder functions should be
+ formatted on multiple lines as usual.
+ (WebCore::Editor::respondToChangedSelection): Added. Forwards to the delete button controller.
+ (WebCore::Editor::respondToChangedContents): Ditto.
+ (WebCore::Editor::Editor): Changed EditorClient parameter to a PassRefPtr since we take ownership.
+
+ * editing/Editor.h: Changed the DeleteButtonController to use an OwnPtr instead of being
+ defined inline to decouple so that we don't have to include DeleteButtonController.h. That way
+ changes to DeleteButtonController.h cause very little to recompile.
+
+ * editing/SelectionController.cpp: (WebCore::SelectionController::setSelection):
+ Updated to call the editor instead of the delete button controller for the selection change.
+
2006-10-21 Anders Carlsson <acarlsson@apple.com>
Reviewed by Darin.
0867D690FE84028FC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */;
- compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
knownRegions = (
English,
productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
projectDirPath = "";
projectRoot = "";
- shouldCheckCompatibility = 1;
targets = (
93F198A508245E59001E9ABC /* WebCore */,
DD041FBE09D9DDBE0010AF2A /* Derived Sources */,
class FrameMac : public Frame
{
public:
- FrameMac(Page*, Element*, EditorClient*);
+ FrameMac(Page*, Element*, PassRefPtr<EditorClient>);
~FrameMac();
void clear();
return selector;
}
-FrameMac::FrameMac(Page* page, Element* ownerElement, EditorClient* client)
+FrameMac::FrameMac(Page* page, Element* ownerElement, PassRefPtr<EditorClient> client)
: Frame(page, ownerElement, client)
, _bridge(nil)
, _mouseDownView(nil)
const char* const DeleteButtonController::buttonElementIdentifier = "WebKit-Editing-Delete-Button";
const char* const DeleteButtonController::outlineElementIdentifier = "WebKit-Editing-Delete-Outline";
-DeleteButtonController::DeleteButtonController(Editor* editor)
- : m_editor(editor)
+DeleteButtonController::DeleteButtonController(Frame* frame)
+ : m_frame(frame)
, m_wasStaticPositioned(false)
, m_wasAutoZIndex(false)
{
}
-void DeleteButtonController::respondToChangedSelection(const Selection& oldSelection)
+static HTMLElement* enclosingDeletableTable(const Selection& selection)
{
- ExceptionCode ec = 0;
- Node* oldTableNode = 0;
- Node* newTableNode = 0;
+ if (!selection.isContentEditable())
+ return 0;
- RefPtr<Range> range = oldSelection.toRange();
- if (oldSelection.isContentEditable() && range.get())
- oldTableNode = enclosingNodeWithTag(range->commonAncestorContainer(ec), tableTag);
- ASSERT(ec == 0);
+ RefPtr<Range> range = selection.toRange();
+ if (!range)
+ return 0;
- range = m_editor->frame()->selectionController()->toRange();
- if (m_editor->frame()->selectionController()->isContentEditable() && range.get())
- newTableNode = enclosingNodeWithTag(range->commonAncestorContainer(ec), tableTag);
+ ExceptionCode ec = 0;
+ Node* container = range->commonAncestorContainer(ec);
+ ASSERT(container);
ASSERT(ec == 0);
- if (oldTableNode != newTableNode) {
- // If the base is inside an editable table, give the table a close widget.
- if (newTableNode)
- show(static_cast<HTMLElement*>(newTableNode));
- else if (oldTableNode)
- hide();
- }
+ // The enclosingNodeWithTag function only works on nodes that are editable
+ // (which is strange, given its name).
+ if (!container->isContentEditable())
+ return 0;
+
+ Node* table = enclosingNodeWithTag(container, tableTag);
+ ASSERT(!table || table->isHTMLElement());
+
+ // The table must be editable too.
+ if (!table->isContentEditable())
+ return 0;
+
+ return static_cast<HTMLElement*>(table);
}
-
-void DeleteButtonController::respondToChangedContents(const Selection& endingSelection)
+
+void DeleteButtonController::respondToChangedSelection(const Selection& oldSelection)
+{
+ HTMLElement* oldTable = enclosingDeletableTable(oldSelection);
+ HTMLElement* newTable = enclosingDeletableTable(m_frame->selectionController()->selection());
+ if (oldTable == newTable)
+ return;
+
+ // If the base is inside an editable table, give the table a close widget.
+ if (newTable)
+ show(newTable);
+ else
+ hide();
+}
+
+void DeleteButtonController::respondToChangedContents()
{
updateOutlineStyle();
}
if (!(element->renderer() && element->renderer()->isRenderBlock()))
return;
- if (!m_editor->shouldShowDeleteInterface(static_cast<HTMLElement*>(element)))
+ if (!m_frame->editor()->shouldShowDeleteInterface(static_cast<HTMLElement*>(element)))
return;
m_element = element;
namespace WebCore {
class DeleteButton;
-class Editor;
+class Frame;
class HTMLElement;
class RenderObject;
class Selection;
class DeleteButtonController {
public:
- DeleteButtonController(Editor*);
+ DeleteButtonController(Frame*);
static const char* const containerElementIdentifier;
static const char* const buttonElementIdentifier;
HTMLElement* target() const { return m_element.get(); };
void respondToChangedSelection(const Selection& oldSelection);
- void respondToChangedContents(const Selection& endingSelection);
+ void respondToChangedContents();
void show(HTMLElement*);
void hide();
private:
void updateOutlineStyle();
- Editor* m_editor;
+ Frame* m_frame;
RefPtr<HTMLElement> m_element;
RefPtr<HTMLElement> m_containerElement;
RefPtr<HTMLElement> m_outlineElement;
#include "config.h"
#include "Editor.h"
+#include "DeleteButtonController.h"
#include "EditorClient.h"
#include "Frame.h"
#include "HTMLElement.h"
namespace WebCore {
// implement as platform-specific
-Pasteboard generalPasteboard()
+static Pasteboard generalPasteboard()
{
return 0;
}
bool Editor::canCopy()
-{ return false; }
+{
+ return false;
+}
bool Editor::canCut()
-{ return false; }
+{
+ return false;
+}
bool Editor::canDelete()
-{ return false; }
+{
+ return false;
+}
bool Editor::canDeleteRange(Range* range)
{
ExceptionCode ec = 0;
- Node *startContainer = range->startContainer(ec);
- Node *endContainer = range->endContainer(ec);
+ Node* startContainer = range->startContainer(ec);
+ Node* endContainer = range->endContainer(ec);
if (!startContainer || !endContainer)
return false;
}
bool Editor::canPaste()
-{ return false; }
+{
+ return false;
+}
bool Editor::canSmartCopyOrDelete()
-{ return false; }
+{
+ return false;
+}
void Editor::deleteSelection()
-{}
+{
+}
void Editor::deleteSelectionWithSmartDelete(bool enabled)
-{}
+{
+}
bool Editor::isSelectionRichlyEditable()
-{ return false; }
+{
+ return false;
+}
void Editor::pasteAsPlainTextWithPasteboard(Pasteboard pasteboard)
-{}
+{
+}
void Editor::pasteWithPasteboard(Pasteboard pasteboard, bool allowPlainText)
-{}
+{
+}
Range* Editor::selectedRange()
-{ return NULL; }
+{
+ return 0;
+}
bool Editor::shouldDeleteRange(Range* range)
{
}
void Editor::writeSelectionToPasteboard(Pasteboard pasteboard)
-{}
+{
+}
bool Editor::shouldShowDeleteInterface(HTMLElement* element)
{
return m_client->shouldShowDeleteInterface(element);
}
+void Editor::respondToChangedSelection(const Selection& oldSelection)
+{
+ m_deleteButtonController->respondToChangedSelection(oldSelection);
+}
+
+void Editor::respondToChangedContents()
+{
+ m_deleteButtonController->respondToChangedContents();
+}
+
// =============================================================================
//
// public editing commands
//
// =============================================================================
-Editor::Editor(Frame* frame, EditorClient* client)
+Editor::Editor(Frame* frame, PassRefPtr<EditorClient> client)
: m_frame(frame)
, m_client(client)
- , m_deleteButtonController(this)
+ , m_deleteButtonController(new DeleteButtonController(frame))
{
}
void Editor::copy()
{
-
if (tryDHTMLCopy())
return; // DHTML did the whole operation
if (!canCopy()) {
#ifndef EDITOR_H
#define EDITOR_H
-#include "DeleteButtonController.h"
+#include <wtf/Forward.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/RefPtr.h>
namespace WebCore {
+class DeleteButtonController;
class EditorClient;
class Frame;
+class HTMLElement;
class Range;
+class Selection;
// make platform-specific and implement - this is temporary placeholder
typedef int Pasteboard;
class Editor {
public:
- Editor(Frame*, EditorClient*);
+ Editor(Frame*, PassRefPtr<EditorClient>);
~Editor();
void cut();
bool shouldShowDeleteInterface(HTMLElement*);
+ void respondToChangedSelection(const Selection& oldSelection);
+ void respondToChangedContents();
+
Frame* frame() const { return m_frame; }
- DeleteButtonController* deleteButtonController() { return &m_deleteButtonController; }
+ DeleteButtonController* deleteButtonController() const { return m_deleteButtonController.get(); }
private:
Frame* m_frame;
RefPtr<EditorClient> m_client;
- DeleteButtonController m_deleteButtonController;
+ OwnPtr<DeleteButtonController> m_deleteButtonController;
bool canCopy();
bool canCut();
#include "config.h"
#include "SelectionController.h"
-#include "DeleteButtonController.h"
#include "Document.h"
#include "Editor.h"
#include "Element.h"
m_frame->selectFrameElementInParentIfFullySelected();
m_frame->notifyRendererOfSelectionChange(userTriggered);
m_frame->respondToChangedSelection(oldSelection, closeTyping);
- m_frame->editor()->deleteButtonController()->respondToChangedSelection(oldSelection);
+ m_frame->editor()->respondToChangedSelection(oldSelection);
if (userTriggered)
m_frame->revealCaret(RenderLayer::gAlignToEdgeIfNeeded);
}
return ownerElement->document()->frame();
}
-Frame::Frame(Page* page, Element* ownerElement, EditorClient* client)
+Frame::Frame(Page* page, Element* ownerElement, PassRefPtr<EditorClient> client)
: d(new FramePrivate(page, parentFromOwnerElement(ownerElement), this, ownerElement, client))
{
AtomicString::init();
registerCommandForUndo(cmd);
}
respondToChangedContents(newSelection);
- editor()->deleteButtonController()->respondToChangedContents(newSelection);
+ editor()->respondToChangedContents();
}
void Frame::unappliedEditing(PassRefPtr<EditCommand> cmd)
d->m_lastEditCommand = 0;
registerCommandForRedo(cmd);
respondToChangedContents(newSelection);
- editor()->deleteButtonController()->respondToChangedContents(newSelection);
+ editor()->respondToChangedContents();
}
void Frame::reappliedEditing(PassRefPtr<EditCommand> cmd)
d->m_lastEditCommand = 0;
registerCommandForUndo(cmd);
respondToChangedContents(newSelection);
- editor()->deleteButtonController()->respondToChangedContents(newSelection);
+ editor()->respondToChangedContents();
}
CSSMutableStyleDeclaration *Frame::typingStyle() const
public:
enum { NoXPosForVerticalArrowNavigation = INT_MIN };
- Frame(Page*, Element*, EditorClient*);
+ Frame(Page*, Element*, PassRefPtr<EditorClient>);
virtual ~Frame();
virtual bool openURL(const KURL&);
#include "Decoder.h"
#include "EditCommand.h"
#include "Editor.h"
+#include "EditorClient.h"
#include "FormData.h"
#include "Frame.h"
#include "FrameTree.h"
class FramePrivate {
public:
- FramePrivate(Page* page, Frame* parent, Frame* thisFrame, Element* ownerElement, EditorClient* client)
+ FramePrivate(Page* page, Frame* parent, Frame* thisFrame, Element* ownerElement, PassRefPtr<EditorClient> client)
: m_page(page)
, m_treeNode(thisFrame, parent)
, m_ownerElement(ownerElement)