#ifndef KHTML_NO_XBL #include "qptrdict.h" #include "xml/dom_docimpl.h" #include "xml/dom_elementimpl.h" #include "rendering/render_style.h" #include "xbl_binding_manager.h" #include "xbl_binding.h" using DOM::DocumentImpl; using DOM::NodeImpl; using DOM::ElementImpl; using khtml::BindingURI; namespace XBL { XBLBindingManager::XBLBindingManager(DocumentImpl* doc) :m_document(doc), m_bindingChainTable(0) { } XBLBindingManager::~XBLBindingManager() { if (m_bindingChainTable) { m_bindingChainTable->setAutoDelete(true); delete m_bindingChainTable; } } XBLBindingChain* XBLBindingManager::getBindingChain(NodeImpl* node) { if (!m_bindingChainTable) return 0; return m_bindingChainTable->find(node); } void XBLBindingManager::setBindingChain(NodeImpl* node, XBLBindingChain* bindingChain) { if (!m_bindingChainTable) m_bindingChainTable = new QPtrDict; if (bindingChain) m_bindingChainTable->replace(node, bindingChain); else m_bindingChainTable->remove(node); } bool XBLBindingManager::loadBindings(NodeImpl* node, BindingURI* bindingURIs, bool isStyleBinding, bool* resolveStyle) { if (resolveStyle) *resolveStyle = false; if (!node->isElementNode()) return true; bool dirty = false; XBLBindingChain* bindingChain = getBindingChain(node); if (bindingChain && isStyleBinding) { // Check to see if the binding is already installed. If so, then we don't need // to do anything. XBLBindingChain* styleBindingChain = bindingChain->firstStyleBindingChain(); if (styleBindingChain) { if (styleBindingChain->markedForDeath()) return false; // The old bindings haven't destroyed themselves/fired their destructors yet. // See if the URIs match. BindingURI* currURI = bindingURIs; XBLBindingChain* currBindingChain = styleBindingChain; for ( ; currURI && currBindingChain; currURI = currURI->next(), currBindingChain = currBindingChain->nextChain()) { if (currBindingChain->uri() != currURI->uri()) { styleBindingChain->markForDeath(); return false; } } if ((currURI && !currBindingChain) || (currBindingChain && !currURI)) { styleBindingChain->markForDeath(); return false; } return bindingChain->loaded(); } } bindingChain = getBindingChain(node); ElementImpl* elt = static_cast(node); for (BindingURI* currURI = bindingURIs; currURI; currURI = currURI->next()) { XBLBindingChain* newBindingChain = new XBLBindingChain(elt, currURI->uri(), isStyleBinding); if (newBindingChain) { if (bindingChain && isStyleBinding) // Style bindings go on the end. Regular bindings go on the front. bindingChain->lastBindingChain()->insertBindingChain(newBindingChain); else { // Place on the front. newBindingChain->insertBindingChain(bindingChain); setBindingChain(node, newBindingChain); } dirty = true; } bindingChain = newBindingChain; } if (!bindingChain) return true; // We did nothing. // If the binding is completely loaded, then return true. Otherwise return false. bindingChain = getBindingChain(node); bool loaded = bindingChain->loaded(); if (loaded && resolveStyle) *resolveStyle = bindingChain->hasStylesheets(); return loaded; } void XBLBindingManager::checkLoadState(ElementImpl* elt) { XBLBindingChain* chain = getBindingChain(elt); if (chain && chain->loaded()) elt->setChanged(); } } #endif // KHTML_NO_XBL