18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "DeleteButtonController.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CachedImage.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CSSMutableStyleDeclaration.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CSSPrimitiveValue.h"
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CSSPropertyNames.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CSSValueKeywords.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "DeleteButton.h"
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Document.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Editor.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Frame.h"
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "htmlediting.h"
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLDivElement.h"
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLNames.h"
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Image.h"
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Node.h"
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Range.h"
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RemoveNodeCommand.h"
45635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "RenderBox.h"
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SelectionController.h"
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace HTMLNames;
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst char* const DeleteButtonController::containerElementIdentifier = "WebKit-Editing-Delete-Container";
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst char* const DeleteButtonController::buttonElementIdentifier = "WebKit-Editing-Delete-Button";
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst char* const DeleteButtonController::outlineElementIdentifier = "WebKit-Editing-Delete-Outline";
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectDeleteButtonController::DeleteButtonController(Frame* frame)
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    : m_frame(frame)
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_wasStaticPositioned(false)
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_wasAutoZIndex(false)
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_disableStack(0)
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool isDeletableElement(const Node* node)
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
662bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!node || !node->isHTMLElement() || !node->inDocument() || !node->rendererIsEditable())
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
69d0825bca7fe65beaee391d30da42e937db621564Steve Block    // In general we want to only draw the UI around object of a certain area, but we still keep the min width/height to
705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // make sure we don't end up with very thin or very short elements getting the UI.
715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    const int minimumArea = 2500;
725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    const int minimumWidth = 48;
735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    const int minimumHeight = 16;
745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    const unsigned minimumVisibleBorders = 1;
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject* renderer = node->renderer();
77635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!renderer || !renderer->isBox())
78635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return false;
79635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Disallow the body element since it isn't practical to delete, and the deletion UI would be clipped.
815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (node->hasTagName(bodyTag))
825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return false;
835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Disallow elements with any overflow clip, since the deletion UI would be clipped as well. <rdar://problem/6840161>
855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (renderer->hasOverflowClip())
865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return false;
875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Disallow Mail blockquotes since the deletion UI would get in the way of editing for these.
895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (isMailBlockquote(node))
905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return false;
915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
92635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    RenderBox* box = toRenderBox(renderer);
93635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    IntRect borderBoundingBox = box->borderBoundingBox();
94635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (borderBoundingBox.width() < minimumWidth || borderBoundingBox.height() < minimumHeight)
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if ((borderBoundingBox.width() * borderBoundingBox.height()) < minimumArea)
985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return false;
995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (renderer->isTable())
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (node->hasTagName(ulTag) || node->hasTagName(olTag) || node->hasTagName(iframeTag))
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (renderer->isPositioned())
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (renderer->isRenderBlock() && !renderer->isTableCell()) {
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RenderStyle* style = renderer->style();
1115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!style)
1125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return false;
1135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // Allow blocks that have background images
1152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (style->hasBackgroundImage()) {
1162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            for (const FillLayer* background = style->backgroundLayers(); background; background = background->next()) {
1172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                if (background->image() && background->image()->canRender(1))
1182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    return true;
1192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            }
1202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
1215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // Allow blocks with a minimum number of non-transparent borders
1235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        unsigned visibleBorders = style->borderTop().isVisible() + style->borderBottom().isVisible() + style->borderLeft().isVisible() + style->borderRight().isVisible();
1245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (visibleBorders >= minimumVisibleBorders)
1255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return true;
1265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // Allow blocks that have a different background from it's parent
128a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ContainerNode* parentNode = node->parentNode();
1295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!parentNode)
1305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return false;
1315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        RenderObject* parentRenderer = parentNode->renderer();
1335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!parentRenderer)
1345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return false;
1355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        RenderStyle* parentStyle = parentRenderer->style();
1375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!parentStyle)
1385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return false;
1395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
140e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block        if (renderer->hasBackground() && (!parentRenderer->hasBackground() || style->visitedDependentColor(CSSPropertyBackgroundColor) != parentStyle->visitedDependentColor(CSSPropertyBackgroundColor)))
1415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return true;
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic HTMLElement* enclosingDeletableElement(const VisibleSelection& selection)
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!selection.isContentEditable())
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    RefPtr<Range> range = selection.toNormalizedRange();
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!range)
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ExceptionCode ec = 0;
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* container = range->commonAncestorContainer(ec);
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(container);
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(ec == 0);
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // The enclosingNodeOfType function only works on nodes that are editable
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // (which is strange, given its name).
1632bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!container->rendererIsEditable())
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
16665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    Node* element = enclosingNodeOfType(firstPositionInNode(container), &isDeletableElement);
1672bde8e466a4451c7319e3a072d118917957d6554Steve Block    return element && element->isHTMLElement() ? toHTMLElement(element) : 0;
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid DeleteButtonController::respondToChangedSelection(const VisibleSelection& oldSelection)
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!enabled())
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    HTMLElement* oldElement = enclosingDeletableElement(oldSelection);
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    HTMLElement* newElement = enclosingDeletableElement(m_frame->selection()->selection());
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (oldElement == newElement)
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If the base is inside a deletable element, give the element a delete widget.
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (newElement)
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        show(newElement);
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        hide();
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid DeleteButtonController::createDeletionUI()
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1895af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    RefPtr<HTMLDivElement> container = HTMLDivElement::create(m_target->document());
190545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    container->setIdAttribute(containerElementIdentifier);
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CSSMutableStyleDeclaration* style = container->getInlineStyleDecl();
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    style->setProperty(CSSPropertyWebkitUserDrag, CSSValueNone);
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    style->setProperty(CSSPropertyWebkitUserSelect, CSSValueNone);
1952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    style->setProperty(CSSPropertyWebkitUserModify, CSSValueReadOnly);
1968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    style->setProperty(CSSPropertyVisibility, CSSValueHidden);
1978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    style->setProperty(CSSPropertyPosition, CSSValueAbsolute);
1988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    style->setProperty(CSSPropertyCursor, CSSValueDefault);
1998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    style->setProperty(CSSPropertyTop, "0");
2008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    style->setProperty(CSSPropertyRight, "0");
2018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    style->setProperty(CSSPropertyBottom, "0");
2028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    style->setProperty(CSSPropertyLeft, "0");
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2045af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    RefPtr<HTMLDivElement> outline = HTMLDivElement::create(m_target->document());
205545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    outline->setIdAttribute(outlineElementIdentifier);
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const int borderWidth = 4;
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const int borderRadius = 6;
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    style = outline->getInlineStyleDecl();
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    style->setProperty(CSSPropertyPosition, CSSValueAbsolute);
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    style->setProperty(CSSPropertyZIndex, String::number(-1000000));
213635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    style->setProperty(CSSPropertyTop, String::number(-borderWidth - m_target->renderBox()->borderTop()) + "px");
214635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    style->setProperty(CSSPropertyRight, String::number(-borderWidth - m_target->renderBox()->borderRight()) + "px");
215635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    style->setProperty(CSSPropertyBottom, String::number(-borderWidth - m_target->renderBox()->borderBottom()) + "px");
216635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    style->setProperty(CSSPropertyLeft, String::number(-borderWidth - m_target->renderBox()->borderLeft()) + "px");
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    style->setProperty(CSSPropertyBorder, String::number(borderWidth) + "px solid rgba(0, 0, 0, 0.6)");
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    style->setProperty(CSSPropertyWebkitBorderRadius, String::number(borderRadius) + "px");
2198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    style->setProperty(CSSPropertyVisibility, CSSValueVisible);
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ExceptionCode ec = 0;
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    container->appendChild(outline.get(), ec);
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(ec == 0);
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (ec)
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2275af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    RefPtr<DeleteButton> button = DeleteButton::create(m_target->document());
228545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    button->setIdAttribute(buttonElementIdentifier);
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const int buttonWidth = 30;
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const int buttonHeight = 30;
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const int buttonBottomShadowOffset = 2;
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    style = button->getInlineStyleDecl();
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    style->setProperty(CSSPropertyPosition, CSSValueAbsolute);
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    style->setProperty(CSSPropertyZIndex, String::number(1000000));
237635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    style->setProperty(CSSPropertyTop, String::number((-buttonHeight / 2) - m_target->renderBox()->borderTop() - (borderWidth / 2) + buttonBottomShadowOffset) + "px");
238635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    style->setProperty(CSSPropertyLeft, String::number((-buttonWidth / 2) - m_target->renderBox()->borderLeft() - (borderWidth / 2)) + "px");
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    style->setProperty(CSSPropertyWidth, String::number(buttonWidth) + "px");
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    style->setProperty(CSSPropertyHeight, String::number(buttonHeight) + "px");
2418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    style->setProperty(CSSPropertyVisibility, CSSValueVisible);
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<Image> buttonImage = Image::loadPlatformResource("deleteButton");
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (buttonImage->isNull())
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    button->setCachedImage(new CachedImage(buttonImage.get()));
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    container->appendChild(button.get(), ec);
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(ec == 0);
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (ec)
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_containerElement = container.release();
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_outlineElement = outline.release();
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_buttonElement = button.release();
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid DeleteButtonController::show(HTMLElement* element)
2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    hide();
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!enabled() || !element || !element->inDocument() || !isDeletableElement(element))
2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!m_frame->editor()->shouldShowDeleteInterface(toHTMLElement(element)))
2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // we rely on the renderer having current information, so we should update the layout if needed
2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_frame->document()->updateLayoutIgnorePendingStylesheets();
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_target = element;
2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_containerElement) {
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        createDeletionUI();
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!m_containerElement) {
2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            hide();
2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ExceptionCode ec = 0;
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_target->appendChild(m_containerElement.get(), ec);
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(ec == 0);
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (ec) {
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        hide();
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_target->renderer()->style()->position() == StaticPosition) {
2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_target->getInlineStyleDecl()->setProperty(CSSPropertyPosition, CSSValueRelative);
2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_wasStaticPositioned = true;
2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_target->renderer()->style()->hasAutoZIndex()) {
2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_target->getInlineStyleDecl()->setProperty(CSSPropertyZIndex, "0");
2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_wasAutoZIndex = true;
2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid DeleteButtonController::hide()
3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_outlineElement = 0;
3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_buttonElement = 0;
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ExceptionCode ec = 0;
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_containerElement && m_containerElement->parentNode())
3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_containerElement->parentNode()->removeChild(m_containerElement.get(), ec);
3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_target) {
3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_wasStaticPositioned)
3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_target->getInlineStyleDecl()->setProperty(CSSPropertyPosition, CSSValueStatic);
3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_wasAutoZIndex)
3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_target->getInlineStyleDecl()->setProperty(CSSPropertyZIndex, CSSValueAuto);
3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_wasStaticPositioned = false;
3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_wasAutoZIndex = false;
3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid DeleteButtonController::enable()
3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(m_disableStack > 0);
3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_disableStack > 0)
3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_disableStack--;
3268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (enabled()) {
3278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // Determining if the element is deletable currently depends on style
3288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // because whether something is editable depends on style, so we need
3298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // to recalculate style before calling enclosingDeletableElement.
3305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_frame->document()->updateStyleIfNeeded();
3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        show(enclosingDeletableElement(m_frame->selection()->selection()));
3328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid DeleteButtonController::disable()
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (enabled())
3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        hide();
3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_disableStack++;
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid DeleteButtonController::deleteTarget()
3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!enabled() || !m_target)
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<Node> element = m_target;
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    hide();
3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Because the deletion UI only appears when the selection is entirely
3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // within the target, we unconditionally update the selection to be
3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // a caret where the target had been.
353231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    Position pos = positionInParentBeforeNode(element.get());
3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    applyCommand(RemoveNodeCommand::create(element.release()));
3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_frame->selection()->setSelection(VisiblePosition(pos));
3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore
359