<commit_before>/*
 * Copyright 2010-2012 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "HTMLElementImp.h"

#include <boost/bind.hpp>

#include <org/w3c/dom/events/MouseEvent.h>

#include "DocumentImp.h"
#include "EventImp.h"
#include "ECMAScript.h"
#include "css/Box.h"
#include "css/CSSParser.h"
#include "css/CSSStyleDeclarationImp.h"
#include "HTMLBindingElementImp.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

HTMLElementImp::HTMLElementImp(DocumentImp* ownerDocument, const std::u16string& localName) :
    ObjectMixin(ownerDocument, localName, u"http://www.w3.org/1999/xhtml"),
    style(0),
    scrollTop(0),
    scrollLeft(0),
    clickListener(boost::bind(&HTMLElementImp::handleClick, this, _1)),
    mouseMoveListener(boost::bind(&HTMLElementImp::handleMouseMove, this, _1)),
    shadowTree(0),
    shadowTarget(0),
    shadowImplementation(0)
{
    addEventListener(u"click", &clickListener);
    addEventListener(u"mousemove", &mouseMoveListener);
}

HTMLElementImp::HTMLElementImp(HTMLElementImp* org, bool deep) :
    ObjectMixin(org, deep),
    style(org->style),  // TODO: clone
    scrollTop(0),
    scrollLeft(0),
    clickListener(boost::bind(&HTMLElementImp::handleClick, this, _1)),
    mouseMoveListener(boost::bind(&HTMLElementImp::handleMouseMove, this, _1)),
    shadowTree(0),            // TODO: clone
    shadowTarget(0),          // TODO: clone
    shadowImplementation(0)   // TODO: clone
{
    addEventListener(u"click", &clickListener);
    addEventListener(u"mousemove", &mouseMoveListener);
}

HTMLElementImp::~HTMLElementImp()
{
}

void HTMLElementImp::handleClick(events::Event event)
{
    if (event.getDefaultPrevented())
        return;
    events::MouseEvent mouse = interface_cast<events::MouseEvent>(event);
    switch (mouse.getButton()) {
    case 0:
        moveX = mouse.getScreenX();
        moveY = mouse.getScreenY();
        break;
    default:
        break;
    }
}

void HTMLElementImp::handleMouseMove(events::Event event)
{
    if (event.getDefaultPrevented())
        return;
    events::MouseEvent mouse = interface_cast<events::MouseEvent>(event);
    unsigned short buttons = mouse.getButtons();
    if (buttons & 1) {
        setScrollTop(getScrollTop() + moveY - mouse.getScreenY());
        setScrollLeft(getScrollLeft() + moveX - mouse.getScreenX());
    }
    moveX = mouse.getScreenX();
    moveY = mouse.getScreenY();
}

void HTMLElementImp::eval()
{
    DocumentWindowPtr window = getOwnerDocumentImp()->activate();
    Nullable<std::u16string> attr = getAttribute(u"style");
    if (attr.hasValue()) {
        CSSParser parser;
        style = parser.parseDeclarations(attr.value());
        parser.getStyleDeclaration()->setOwner(this);
    }
    attr = getAttribute(u"onclick");
    if (attr.hasValue())
        setOnclick(window->getContext()->compileFunction(attr.value()));
    attr = getAttribute(u"onload");
    if (attr.hasValue())
        setOnload(window->getContext()->compileFunction(attr.value()));
}

Box* HTMLElementImp::getBox()
{
    html::Window window = getOwnerDocument().getDefaultView();
    if (!window)
        return 0;
    css::CSSStyleDeclaration style = window.getComputedStyle(this);
    if (!style)
        return 0;
    // TODO: Fix MVC violation
    CSSStyleDeclarationImp* imp = dynamic_cast<CSSStyleDeclarationImp*>(style.self());
    if (!imp)
        return 0;
    return imp->getBox();
}

// XBL 2.0 internal
void HTMLElementImp::generateShadowContent(CSSStyleDeclarationImp* style)
{
    if (style->binding.getValue() != CSSBindingValueImp::Uri)
        return;
    if (getShadowTree())  // already attached?
        return;
    DocumentImp* document = getOwnerDocumentImp();
    assert(document);
    URL base(document->getDocumentURI());
    URL url(base, style->binding.getURL());
    if (!base.isSameExceptFragments(url))
        return;   // TODO: Support external bindings later.
    std::u16string hash = url.getHash();
    if (hash[0] == '#')
        hash.erase(0, 1);
    Element element = document->getElementById(hash);
    if (!element)
        return;
    auto binding = dynamic_cast<HTMLBindingElementImp*>(element.self());
    if (!binding)
        return;
    if (html::HTMLTemplateElement shadowTree = binding->cloneTemplate()) {
        setShadowTree(shadowTree);
        shadowTarget = new(std::nothrow) EventTargetImp;
        DocumentWindowPtr window = getOwnerDocumentImp()->activate();
        ECMAScriptContext* context = window->getContext();
        xbl2::XBLImplementation implementation = context->xblCreateImplementation(shadowTarget, binding->getImplementation(), this, shadowTree);
        setShadowImplementation(implementation);
        implementation.xblEnteredDocument();
    }
}

void HTMLElementImp::invoke(EventImp* event)
{
    if (!shadowTarget) {
        EventTargetImp::invoke(event);
        return;<commit_msg>(HTMLElementImp::generateShadowContent) : Clean up.<commit_after>/*
 * Copyright 2010-2012 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "HTMLElementImp.h"

#include <boost/bind.hpp>

#include <org/w3c/dom/events/MouseEvent.h>

#include "DocumentImp.h"
#include "EventImp.h"
#include "ECMAScript.h"
#include "css/Box.h"
#include "css/CSSParser.h"
#include "css/CSSStyleDeclarationImp.h"
#include "HTMLBindingElementImp.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

HTMLElementImp::HTMLElementImp(DocumentImp* ownerDocument, const std::u16string& localName) :
    ObjectMixin(ownerDocument, localName, u"http://www.w3.org/1999/xhtml"),
    style(0),
    scrollTop(0),
    scrollLeft(0),
    clickListener(boost::bind(&HTMLElementImp::handleClick, this, _1)),
    mouseMoveListener(boost::bind(&HTMLElementImp::handleMouseMove, this, _1)),
    shadowTree(0),
    shadowTarget(0),
    shadowImplementation(0)
{
    addEventListener(u"click", &clickListener);
    addEventListener(u"mousemove", &mouseMoveListener);
}

HTMLElementImp::HTMLElementImp(HTMLElementImp* org, bool deep) :
    ObjectMixin(org, deep),
    style(org->style),  // TODO: clone
    scrollTop(0),
    scrollLeft(0),
    clickListener(boost::bind(&HTMLElementImp::handleClick, this, _1)),
    mouseMoveListener(boost::bind(&HTMLElementImp::handleMouseMove, this, _1)),
    shadowTree(0),            // TODO: clone
    shadowTarget(0),          // TODO: clone
    shadowImplementation(0)   // TODO: clone
{
    addEventListener(u"click", &clickListener);
    addEventListener(u"mousemove", &mouseMoveListener);
}

HTMLElementImp::~HTMLElementImp()
{
}

void HTMLElementImp::handleClick(events::Event event)
{
    if (event.getDefaultPrevented())
        return;
    events::MouseEvent mouse = interface_cast<events::MouseEvent>(event);
    switch (mouse.getButton()) {
    case 0:
        moveX = mouse.getScreenX();
        moveY = mouse.getScreenY();
        break;
    default:
        break;
    }
}

void HTMLElementImp::handleMouseMove(events::Event event)
{
    if (event.getDefaultPrevented())
        return;
    events::MouseEvent mouse = interface_cast<events::MouseEvent>(event);
    unsigned short buttons = mouse.getButtons();
    if (buttons & 1) {
        setScrollTop(getScrollTop() + moveY - mouse.getScreenY());
        setScrollLeft(getScrollLeft() + moveX - mouse.getScreenX());
    }
    moveX = mouse.getScreenX();
    moveY = mouse.getScreenY();
}

void HTMLElementImp::eval()
{
    DocumentWindowPtr window = getOwnerDocumentImp()->activate();
    Nullable<std::u16string> attr = getAttribute(u"style");
    if (attr.hasValue()) {
        CSSParser parser;
        style = parser.parseDeclarations(attr.value());
        parser.getStyleDeclaration()->setOwner(this);
    }
    attr = getAttribute(u"onclick");
    if (attr.hasValue())
        setOnclick(window->getContext()->compileFunction(attr.value()));
    attr = getAttribute(u"onload");
    if (attr.hasValue())
        setOnload(window->getContext()->compileFunction(attr.value()));
}

Box* HTMLElementImp::getBox()
{
    html::Window window = getOwnerDocument().getDefaultView();
    if (!window)
        return 0;
    css::CSSStyleDeclaration style = window.getComputedStyle(this);
    if (!style)
        return 0;
    // TODO: Fix MVC violation
    CSSStyleDeclarationImp* imp = dynamic_cast<CSSStyleDeclarationImp*>(style.self());
    if (!imp)
        return 0;
    return imp->getBox();
}

// XBL 2.0 internal
void HTMLElementImp::generateShadowContent(CSSStyleDeclarationImp* style)
{
    if (style->binding.getValue() != CSSBindingValueImp::Uri)
        return;
    if (getShadowTree())  // already attached?
        return;
    DocumentImp* document = getOwnerDocumentImp();
    assert(document);
    URL base(document->getDocumentURI());
    URL url(base, style->binding.getURL());
    if (!base.isSameExceptFragments(url))
        return;   // TODO: Support external bindings later.
    std::u16string hash = url.getHash();
    if (hash[0] == '#')
        hash.erase(0, 1);
    Element element = document->getElementById(hash);
    if (!element)
        return;
    auto binding = dynamic_cast<HTMLBindingElementImp*>(element.self());
    if (!binding)
        return;
    if (html::HTMLTemplateElement shadowTree = binding->cloneTemplate()) {
        setShadowTree(shadowTree);
        shadowTarget = new(std::nothrow) EventTargetImp;
        DocumentWindowPtr window = document->activate();
        ECMAScriptContext* context = window->getContext();
        xbl2::XBLImplementation implementation = context->xblCreateImplementation(shadowTarget, binding->getImplementation(), this, shadowTree);
        setShadowImplementation(implementation);
        implementation.xblEnteredDocument();
    }
}

void HTMLElementImp::invoke(EventImp* event)
{
    if (!shadowTarget) {
        EventTargetImp::invoke(event);
        return;
{'fraction_non_alphanumeric': 0.1311897106109325, 'fraction_numerical': 0.009370693615066605, 'mean_word_length': 3.892584269662921, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2200624', 'n_tokens_mistral': 3223, 'n_tokens_neox': 3216, 'n_words': 693}