📄 containernode.cpp
字号:
// If the child has a parent again, just stop what we're doing, because // that means someone is doing something with DOM mutation -- can't re-parent // a child that already has a parent. if (child->parentNode()) break; } // Append child to the end of the list childCountDelta++; forbidEventDispatch(); child->setParent(this); if (m_lastChild) { child->setPreviousSibling(m_lastChild); m_lastChild->setNextSibling(child.get()); } else m_firstChild = child.get(); m_lastChild = child.get(); allowEventDispatch(); // Dispatch the mutation events dispatchChildInsertionEvents(child.get(), ec); // Add child to the rendering tree if (attached() && !child->attached() && child->parent() == this) { if (shouldLazyAttach) child->lazyAttach(); else child->attach(); } child = nextChild.release(); } document()->setDocumentChanged(true); childrenChanged(false, prev.get(), 0, childCountDelta); dispatchSubtreeModifiedEvent(); return true;}ContainerNode* ContainerNode::addChild(PassRefPtr<Node> newChild){ // This function is only used during parsing. // It does not send any DOM mutation events. // Check for consistency with DTD, but only when parsing HTML. if (document()->isHTMLDocument() && !childAllowed(newChild.get())) return 0; forbidEventDispatch(); Node* last = m_lastChild; appendChildToContainer<Node, ContainerNode>(newChild.get(), this); allowEventDispatch(); document()->incDOMTreeVersion(); if (inDocument()) newChild->insertedIntoDocument(); childrenChanged(true, last, 0, 1); if (newChild->isElementNode()) return static_cast<ContainerNode*>(newChild.get()); return this;}void ContainerNode::suspendPostAttachCallbacks(){ if (!s_attachDepth) { ASSERT(!s_shouldReEnableMemoryCacheCallsAfterAttach); if (Page* page = document()->page()) { if (page->areMemoryCacheClientCallsEnabled()) { page->setMemoryCacheClientCallsEnabled(false); s_shouldReEnableMemoryCacheCallsAfterAttach = true; } } } ++s_attachDepth;}void ContainerNode::resumePostAttachCallbacks(){ if (s_attachDepth == 1) { if (s_postAttachCallbackQueue) dispatchPostAttachCallbacks(); if (s_shouldReEnableMemoryCacheCallsAfterAttach) { s_shouldReEnableMemoryCacheCallsAfterAttach = false; if (Page* page = document()->page()) page->setMemoryCacheClientCallsEnabled(true); } } --s_attachDepth;}void ContainerNode::queuePostAttachCallback(NodeCallback callback, Node* node){ if (!s_postAttachCallbackQueue) s_postAttachCallbackQueue = new NodeCallbackQueue; s_postAttachCallbackQueue->append(std::pair<NodeCallback, RefPtr<Node> >(callback, node));}void ContainerNode::dispatchPostAttachCallbacks(){ // We recalculate size() each time through the loop because a callback // can add more callbacks to the end of the queue. for (size_t i = 0; i < s_postAttachCallbackQueue->size(); ++i) { std::pair<NodeCallback, RefPtr<Node> >& pair = (*s_postAttachCallbackQueue)[i]; NodeCallback callback = pair.first; Node* node = pair.second.get(); callback(node); } s_postAttachCallbackQueue->clear();}void ContainerNode::attach(){ suspendPostAttachCallbacks(); for (Node* child = m_firstChild; child; child = child->nextSibling()) child->attach(); Node::attach(); resumePostAttachCallbacks();}void ContainerNode::detach(){ for (Node* child = m_firstChild; child; child = child->nextSibling()) child->detach(); setHasChangedChild(false); Node::detach();}void ContainerNode::insertedIntoDocument(){ Node::insertedIntoDocument(); insertedIntoTree(false); for (Node* child = m_firstChild; child; child = child->nextSibling()) child->insertedIntoDocument();}void ContainerNode::removedFromDocument(){ Node::removedFromDocument(); setInDocument(false); removedFromTree(false); for (Node* child = m_firstChild; child; child = child->nextSibling()) child->removedFromDocument();}void ContainerNode::insertedIntoTree(bool deep){ if (!deep) return; for (Node* child = m_firstChild; child; child = child->nextSibling()) child->insertedIntoTree(true);}void ContainerNode::removedFromTree(bool deep){ if (!deep) return; for (Node* child = m_firstChild; child; child = child->nextSibling()) child->removedFromTree(true);}void ContainerNode::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta){ Node::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); if (!changedByParser && childCountDelta) document()->nodeChildrenChanged(this); if (document()->hasNodeListCaches()) notifyNodeListsChildrenChanged();}void ContainerNode::cloneChildNodes(ContainerNode *clone){ // disable the delete button so it's elements are not serialized into the markup if (document()->frame()) document()->frame()->editor()->deleteButtonController()->disable(); ExceptionCode ec = 0; for (Node* n = firstChild(); n && !ec; n = n->nextSibling()) clone->appendChild(n->cloneNode(true), ec); if (document()->frame()) document()->frame()->editor()->deleteButtonController()->enable();}// FIXME: This doesn't work correctly with transforms.bool ContainerNode::getUpperLeftCorner(FloatPoint& point) const{ if (!renderer()) return false; // What is this code really trying to do? RenderObject *o = renderer(); RenderObject *p = o; if (!o->isInline() || o->isReplaced()) { point = o->localToAbsolute(); return true; } // find the next text/image child, to get a position while (o) { p = o; if (o->firstChild()) o = o->firstChild(); else if (o->nextSibling()) o = o->nextSibling(); else { RenderObject *next = 0; while (!next && o->parent()) { o = o->parent(); next = o->nextSibling(); } o = next; if (!o) break; } if (!o->isInline() || o->isReplaced()) { point = o->localToAbsolute(); return true; } if (p->node() && p->node() == this && o->isText() && !o->isBR() && !toRenderText(o)->firstTextBox()) { // do nothing - skip unrendered whitespace that is a child or next sibling of the anchor } else if ((o->isText() && !o->isBR()) || o->isReplaced()) { point = o->container()->localToAbsolute(); if (o->isText() && toRenderText(o)->firstTextBox()) { point.move(toRenderText(o)->linesBoundingBox().x(), toRenderText(o)->firstTextBox()->root()->topOverflow()); } else if (o->isBox()) { RenderBox* box = toRenderBox(o); point.move(box->x(), box->y()); } return true; } } // If the target doesn't have any children or siblings that could be used to calculate the scroll position, we must be // at the end of the document. Scroll to the bottom. FIXME: who said anything about scrolling? if (!o && document()->view()) { point = FloatPoint(0, document()->view()->contentsHeight()); return true; } return false;}// FIXME: This doesn't work correctly with transforms.bool ContainerNode::getLowerRightCorner(FloatPoint& point) const{ if (!renderer()) return false; RenderObject *o = renderer(); if (!o->isInline() || o->isReplaced()) { RenderBox* box = toRenderBox(o); point = o->localToAbsolute(); point.move(box->width(), box->height()); return true; } // find the last text/image child, to get a position while (o) { if (o->lastChild()) o = o->lastChild(); else if (o->previousSibling()) o = o->previousSibling(); else { RenderObject *prev = 0; while(!prev) { o = o->parent(); if (!o) return false; prev = o->previousSibling(); } o = prev; } if (o->isText() || o->isReplaced()) { point = o->container()->localToAbsolute(); if (o->isText()) { RenderText* text = toRenderText(o); IntRect linesBox = text->linesBoundingBox(); point.move(linesBox.x() + linesBox.width(), linesBox.y() + linesBox.height()); } else { RenderBox* box = toRenderBox(o); point.move(box->x() + box->width(), box->y() + box->height()); } return true; } } return true;}IntRect ContainerNode::getRect() const{ FloatPoint upperLeft, lowerRight; bool foundUpperLeft = getUpperLeftCorner(upperLeft); bool foundLowerRight = getLowerRightCorner(lowerRight); // If we've found one corner, but not the other, // then we should just return a point at the corner that we did find. if (foundUpperLeft != foundLowerRight) { if (foundUpperLeft) lowerRight = upperLeft; else upperLeft = lowerRight; } lowerRight.setX(max(upperLeft.x(), lowerRight.x())); lowerRight.setY(max(upperLeft.y(), lowerRight.y())); return enclosingIntRect(FloatRect(upperLeft, lowerRight - upperLeft));}void ContainerNode::setFocus(bool received){ if (focused() == received) return; Node::setFocus(received); // note that we need to recalc the style setChanged();}void ContainerNode::setActive(bool down, bool pause){ if (down == active()) return; Node::setActive(down); // note that we need to recalc the style // FIXME: Move to Element if (renderer()) { bool reactsToPress = renderer()->style()->affectedByActiveRules(); if (reactsToPress) setChanged(); if (renderer() && renderer()->style()->hasAppearance()) { if (theme()->stateChanged(renderer(), PressedState)) reactsToPress = true; } if (reactsToPress && pause) { // The delay here is subtle. It relies on an assumption, namely that the amount of time it takes // to repaint the "down" state of the control is about the same time as it would take to repaint the // "up" state. Once you assume this, you can just delay for 100ms - that time (assuming that after you // leave this method, it will be about that long before the flush of the up state happens again).#ifdef HAVE_FUNC_USLEEP double startTime = currentTime();#endif // Ensure there are no pending changes Document::updateDocumentsRendering(); // Do an immediate repaint. if (renderer()) renderer()->repaint(true); // FIXME: Find a substitute for usleep for Win32. // Better yet, come up with a way of doing this that doesn't use this sort of thing at all. #ifdef HAVE_FUNC_USLEEP // Now pause for a small amount of time (1/10th of a second from before we repainted in the pressed state) double remainingTime = 0.1 - (currentTime() - startTime); if (remainingTime > 0) usleep(static_cast<useconds_t>(remainingTime * 1000000.0));#endif } }}void ContainerNode::setHovered(bool over){ if (over == hovered()) return; Node::setHovered(over); // note that we need to recalc the style // FIXME: Move to Element if (renderer()) { if (renderer()->style()->affectedByHoverRules()) setChanged(); if (renderer() && renderer()->style()->hasAppearance()) theme()->stateChanged(renderer(), HoverState); }}unsigned ContainerNode::childNodeCount() const{ unsigned count = 0; Node *n; for (n = firstChild(); n; n = n->nextSibling()) count++; return count;}Node *ContainerNode::childNode(unsigned index) const{ unsigned i; Node *n = firstChild(); for (i = 0; n != 0 && i < index; i++) n = n->nextSibling(); return n;}static void dispatchChildInsertionEvents(Node* child, ExceptionCode& ec){ ASSERT(!eventDispatchForbidden()); RefPtr<Node> c = child; DocPtr<Document> doc = child->document(); if (c->parentNode() && c->parentNode()->inDocument()) c->insertedIntoDocument(); else c->insertedIntoTree(true); if (c->parentNode() && doc->hasListenerType(Document::DOMNODEINSERTED_LISTENER)) { ec = 0; c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, false, c->parentNode(), String(), String(), String(), 0), ec); if (ec) return; } // dispatch the DOMNodeInsertedIntoDocument event to all descendants if (c->inDocument() && doc->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) for (; c; c = c->traverseNextNode(child)) { ec = 0; c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false, false, 0, String(), String(), String(), 0), ec); if (ec) return; }}static void dispatchChildRemovalEvents(Node* child, ExceptionCode& ec){ RefPtr<Node> c = child; DocPtr<Document> doc = child->document(); // update auxiliary doc info (e.g. iterators) to note that node is being removed doc->nodeWillBeRemoved(child); // dispatch pre-removal mutation events if (c->parentNode() && doc->hasListenerType(Document::DOMNODEREMOVED_LISTENER)) { ec = 0; c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, false, c->parentNode(), String(), String(), String(), 0), ec); if (ec) return; } // dispatch the DOMNodeRemovedFromDocument event to all descendants if (c->inDocument() && doc->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) for (; c; c = c->traverseNextNode(child)) { ec = 0; c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false, false, 0, String(), String(), String(), 0), ec); if (ec) return; }}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -