|
|
|
/*
|
|
|
|
Copyright (C) 2001-2003 KSVG Team
|
|
|
|
This file is part of the KDE project
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <tqxml.h>
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
|
|
|
|
#include "SVGEvent.h"
|
|
|
|
#include "SVGEventImpl.h"
|
|
|
|
#include "SVGHelperImpl.h"
|
|
|
|
#include "SVGElementImpl.h"
|
|
|
|
#include "SVGDocumentImpl.h"
|
|
|
|
#include "SVGSVGElementImpl.h"
|
|
|
|
|
|
|
|
using namespace KSVG;
|
|
|
|
|
|
|
|
#include "SVGElementImpl.lut.h"
|
|
|
|
#include "ksvg_scriptinterpreter.h"
|
|
|
|
#include "ksvg_ecma.h"
|
|
|
|
|
|
|
|
SVGElementImpl::Factory *SVGElementImpl::Factory::m_instance = 0;
|
|
|
|
|
|
|
|
SVGElementImpl::SVGElementImpl(DOM::ElementImpl *impl) : DOM::DomShared(), DOM::Element(impl), SVGDOMElementBridge(static_cast<DOM::Element>(*this))
|
|
|
|
{
|
|
|
|
KSVG_EMPTY_FLAGS
|
|
|
|
|
|
|
|
m_ownerSVGElement = 0;
|
|
|
|
m_viewportElement = 0;
|
|
|
|
m_ownerDoc = 0;
|
|
|
|
|
|
|
|
m_mouseOver = false;
|
|
|
|
m_focus = false;
|
|
|
|
|
|
|
|
m_eventListeners.setAutoDelete(true);
|
|
|
|
m_attributes.setAutoDelete(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
SVGElementImpl::~SVGElementImpl()
|
|
|
|
{
|
|
|
|
if(m_ownerSVGElement)
|
|
|
|
m_ownerSVGElement->deref();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVGElementImpl::setEventListener(int id, SVGEventListener *listener)
|
|
|
|
{
|
|
|
|
if(listener)
|
|
|
|
listener->ref();
|
|
|
|
|
|
|
|
removeEventListener(id);
|
|
|
|
|
|
|
|
if(listener)
|
|
|
|
{
|
|
|
|
SVGRegisteredEventListener *rl = new SVGRegisteredEventListener(static_cast<SVGEvent::EventId>(id), listener, false);
|
|
|
|
m_eventListeners.append(rl);
|
|
|
|
|
|
|
|
listener->deref();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int SVGElementImpl::getEventListeners(bool local)
|
|
|
|
{
|
|
|
|
int events = 0;
|
|
|
|
|
|
|
|
TQPtrListIterator<SVGRegisteredEventListener> it(m_eventListeners);
|
|
|
|
for(; it.current(); ++it)
|
|
|
|
events |= (1 << it.current()->id);
|
|
|
|
|
|
|
|
if(local)
|
|
|
|
return events;
|
|
|
|
|
|
|
|
for(DOM::Node node = parentNode(); !node.isNull(); node = node.parentNode())
|
|
|
|
{
|
|
|
|
SVGElementImpl *element = ownerDoc()->getElementFromHandle(node.handle());
|
|
|
|
|
|
|
|
if(element)
|
|
|
|
{
|
|
|
|
TQPtrListIterator<SVGRegisteredEventListener> it(element->m_eventListeners);
|
|
|
|
for(; it.current(); ++it)
|
|
|
|
events |= (1 << it.current()->id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return events;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVGElementImpl::setupEventListeners(SVGDocumentImpl *doc, SVGDocumentImpl *newDoc)
|
|
|
|
{
|
|
|
|
if(!doc || !newDoc)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Changes the document where the eventlisteners are registered
|
|
|
|
// Needed for parseXML'ed elements with events, their listeners
|
|
|
|
// are created in the temporary document fragment and need to be
|
|
|
|
// registered in the main document (Niko)
|
|
|
|
TQPtrListIterator<SVGRegisteredEventListener> it(m_eventListeners);
|
|
|
|
for(; it.current(); ++it)
|
|
|
|
{
|
|
|
|
SVGRegisteredEventListener *current = it.current();
|
|
|
|
|
|
|
|
TQString valueOfCurrent = newDoc->ecmaEngine()->valueOfEventListener(current->listener);
|
|
|
|
setEventListener(current->id, doc->createEventListener(valueOfCurrent));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SVGElementImpl::hasEventListener(int id, bool local)
|
|
|
|
{
|
|
|
|
// First check if we have the listener, locally
|
|
|
|
TQPtrListIterator<SVGRegisteredEventListener> it(m_eventListeners);
|
|
|
|
for(; it.current(); ++it)
|
|
|
|
{
|
|
|
|
if(it.current()->id == id)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We have no local listeners, if we are just interessted
|
|
|
|
// in those listeners, then return now...
|
|
|
|
if(local)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Check every parent element
|
|
|
|
for(DOM::Node node = parentNode(); !node.isNull(); node = node.parentNode())
|
|
|
|
{
|
|
|
|
SVGElementImpl *element = ownerDoc()->getElementFromHandle(node.handle());
|
|
|
|
|
|
|
|
if(element)
|
|
|
|
{
|
|
|
|
TQPtrListIterator<SVGRegisteredEventListener> it(element->m_eventListeners);
|
|
|
|
for(; it.current(); ++it)
|
|
|
|
{
|
|
|
|
if(it.current()->id == id)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVGElementImpl::removeEventListener(int id)
|
|
|
|
{
|
|
|
|
TQPtrListIterator<SVGRegisteredEventListener> it(m_eventListeners);
|
|
|
|
for(; it.current(); ++it)
|
|
|
|
{
|
|
|
|
if(it.current()->id == id)
|
|
|
|
{
|
|
|
|
m_eventListeners.removeRef(it.current());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVGElementImpl::handleLocalEvents(SVGEventImpl *evt, bool useCapture)
|
|
|
|
{
|
|
|
|
TQPtrListIterator<SVGRegisteredEventListener> it(m_eventListeners);
|
|
|
|
for(; it.current(); ++it)
|
|
|
|
{
|
|
|
|
if(it.current()->id == evt->id() && it.current()->useCapture == useCapture)
|
|
|
|
{
|
|
|
|
it.current()->listener->handleEvent(evt);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVGElementImpl::defaultEventHandler(SVGEventImpl *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
@namespace KSVG
|
|
|
|
@begin SVGElementImpl::s_hashTable 23
|
|
|
|
id SVGElementImpl::ElementId DontDelete
|
|
|
|
ownerSVGElement SVGElementImpl::OwnerSvgElement DontDelete|ReadOnly
|
|
|
|
viewportElement SVGElementImpl::ViewportElement DontDelete|ReadOnly
|
|
|
|
xmlbase SVGElementImpl::XmlBase DontDelete
|
|
|
|
base SVGElementImpl::XmlBase DontDelete
|
|
|
|
onmouseup SVGElementImpl::OnMouseUp DontDelete
|
|
|
|
onmousedown SVGElementImpl::OnMouseDown DontDelete
|
|
|
|
onmousemove SVGElementImpl::OnMouseMove DontDelete
|
|
|
|
onmouseover SVGElementImpl::OnMouseOver DontDelete
|
|
|
|
onmouseout SVGElementImpl::OnMouseOut DontDelete
|
|
|
|
onclick SVGElementImpl::OnClick DontDelete
|
|
|
|
onmouseclick SVGElementImpl::OnClick DontDelete
|
|
|
|
onactivate SVGElementImpl::OnActivate DontDelete
|
|
|
|
onkeydown SVGElementImpl::OnKeyDown DontDelete
|
|
|
|
onkeyup SVGElementImpl::OnKeyUp DontDelete
|
|
|
|
onkeypress SVGElementImpl::OnKeyPress DontDelete
|
|
|
|
onload SVGElementImpl::OnLoad DontDelete
|
|
|
|
onfocusin SVGElementImpl::OnFocusIn DontDelete
|
|
|
|
onfocusout SVGElementImpl::OnFocusOut DontDelete
|
|
|
|
onerror SVGElementImpl::OnError DontDelete
|
|
|
|
onabort SVGElementImpl::OnAbort DontDelete
|
|
|
|
@end
|
|
|
|
@namespace KSVG
|
|
|
|
@begin SVGElementImplProto::s_hashTable 5
|
|
|
|
getStyle SVGElementImpl::GetStyle DontDelete|Function 0
|
|
|
|
setProperty SVGElementImpl::SetProperty DontDelete|Function 2
|
|
|
|
getPropertyValue SVGElementImpl::GetPropertyValue DontDelete|Function 1
|
|
|
|
@end
|
|
|
|
*/
|
|
|
|
|
|
|
|
KSVG_IMPLEMENT_PROTOTYPE("SVGElement", SVGElementImplProto, SVGElementImplProtoFunc)
|
|
|
|
|
|
|
|
Value SVGElementImpl::getValueProperty(ExecState *exec, int token) const
|
|
|
|
{
|
|
|
|
switch(token)
|
|
|
|
{
|
|
|
|
case ElementId:
|
|
|
|
return String(id().string());
|
|
|
|
case XmlBase:
|
|
|
|
return String(xmlbase().string());
|
|
|
|
case OwnerSvgElement:
|
|
|
|
return getDOMNode(exec, *ownerSVGElement());
|
|
|
|
case ViewportElement:
|
|
|
|
return getDOMNode(exec, *viewportElement());
|
|
|
|
default:
|
|
|
|
kdWarning() << "Unhandled token in " << k_funcinfo << " : " << token << endl;
|
|
|
|
return Undefined();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVGElementImpl::putValueProperty(ExecState *exec, int token, const Value &value, int)
|
|
|
|
{
|
|
|
|
switch(token)
|
|
|
|
{
|
|
|
|
case ElementId:
|
|
|
|
setId(value.toString(exec).string());
|
|
|
|
break;
|
|
|
|
case XmlBase:
|
|
|
|
setXmlbase(value.toString(exec).string());
|
|
|
|
break;
|
|
|
|
case OnMouseUp:
|
|
|
|
setEventListener(SVGEvent::MOUSEUP_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
|
|
|
|
break;
|
|
|
|
case OnMouseDown:
|
|
|
|
setEventListener(SVGEvent::MOUSEDOWN_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
|
|
|
|
break;
|
|
|
|
case OnMouseMove:
|
|
|
|
setEventListener(SVGEvent::MOUSEMOVE_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
|
|
|
|
break;
|
|
|
|
case OnMouseOver:
|
|
|
|
setEventListener(SVGEvent::MOUSEOVER_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
|
|
|
|
break;
|
|
|
|
case OnMouseOut:
|
|
|
|
setEventListener(SVGEvent::MOUSEOUT_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
|
|
|
|
break;
|
|
|
|
case OnClick:
|
|
|
|
setEventListener(SVGEvent::CLICK_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
|
|
|
|
break;
|
|
|
|
case OnActivate:
|
|
|
|
setEventListener(SVGEvent::DOMACTIVATE_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
|
|
|
|
break;
|
|
|
|
case OnKeyDown:
|
|
|
|
setEventListener(SVGEvent::KEYDOWN_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
|
|
|
|
break;
|
|
|
|
case OnKeyUp:
|
|
|
|
setEventListener(SVGEvent::KEYUP_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
|
|
|
|
break;
|
|
|
|
case OnKeyPress:
|
|
|
|
setEventListener(SVGEvent::KEYPRESS_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
|
|
|
|
break;
|
|
|
|
case OnLoad:
|
|
|
|
setEventListener(SVGEvent::LOAD_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
|
|
|
|
break;
|
|
|
|
case OnFocusIn:
|
|
|
|
setEventListener(SVGEvent::DOMFOCUSIN_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
|
|
|
|
break;
|
|
|
|
case OnFocusOut:
|
|
|
|
setEventListener(SVGEvent::DOMFOCUSOUT_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
|
|
|
|
break;
|
|
|
|
case OnError:
|
|
|
|
setEventListener(SVGEvent::ERROR_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
|
|
|
|
break;
|
|
|
|
case OnAbort:
|
|
|
|
setEventListener(SVGEvent::ABORT_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
kdWarning() << k_funcinfo << "unhandled token " << token << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Value SVGElementImplProtoFunc::call(ExecState *exec, Object &thisObj, const List &args)
|
|
|
|
{
|
|
|
|
KSVG_CHECK_THIS(SVGElementImpl)
|
|
|
|
|
|
|
|
switch(id)
|
|
|
|
{
|
|
|
|
case SVGElementImpl::GetStyle:
|
|
|
|
return obj->cache(exec);
|
|
|
|
case SVGElementImpl::SetProperty:
|
|
|
|
{
|
|
|
|
DOM::DOMString attribute = args[0].toString(exec).qstring().lower();
|
|
|
|
DOM::DOMString value = args[1].toString(exec).qstring();
|
|
|
|
obj->setAttribute(attribute, value);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SVGElementImpl::GetPropertyValue:
|
|
|
|
return String(obj->getAttribute(args[0].toString(exec).qstring()));
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Undefined();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDict<DOM::DOMString> &SVGElementImpl::attributes()
|
|
|
|
{
|
|
|
|
return m_attributes;
|
|
|
|
}
|
|
|
|
|
|
|
|
// khtml overrides
|
|
|
|
void SVGElementImpl::setAttribute(const DOM::DOMString &name, const DOM::DOMString &value)
|
|
|
|
{
|
|
|
|
m_attributes.replace(name.string(), new DOM::DOMString(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Changes internal value. This will have no effect on getAttribute().
|
|
|
|
void SVGElementImpl::setAttributeInternal(const DOM::DOMString &name, const DOM::DOMString &value)
|
|
|
|
{
|
|
|
|
ExecState *exec = ownerDoc()->ecmaEngine()->globalExec();
|
|
|
|
|
|
|
|
static_cast<KSVGScriptInterpreter *>(exec->interpreter())->setAttributeSetMode(true);
|
|
|
|
bridge(exec)->put(exec, Identifier(UString(name)), String(value), KJS::Internal);
|
|
|
|
static_cast<KSVGScriptInterpreter *>(exec->interpreter())->setAttributeSetMode(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// This gets the actual attribute as set in the svg source
|
|
|
|
DOM::DOMString SVGElementImpl::getAttribute(const DOM::DOMString &name) const
|
|
|
|
{
|
|
|
|
DOM::DOMString *result = m_attributes[name.string()];
|
|
|
|
if(result)
|
|
|
|
return *result;
|
|
|
|
else
|
|
|
|
return DOM::DOMString();
|
|
|
|
}
|
|
|
|
|
|
|
|
// This gets the internal, real-time value. This means it can return a default value
|
|
|
|
// for an attribute even if its not explicitly set in the svg source.
|
|
|
|
DOM::DOMString SVGElementImpl::getAttributeInternal(const DOM::DOMString &name)
|
|
|
|
{
|
|
|
|
ExecState *exec = ownerDoc()->ecmaEngine()->globalExec();
|
|
|
|
|
|
|
|
DOM::DOMString retVal;
|
|
|
|
|
|
|
|
static_cast<KSVGScriptInterpreter *>(exec->interpreter())->setAttributeGetMode(true);
|
|
|
|
retVal = bridge(exec)->get(exec, Identifier(UString(name))).toString(exec).string();
|
|
|
|
static_cast<KSVGScriptInterpreter *>(exec->interpreter())->setAttributeGetMode(false);
|
|
|
|
|
|
|
|
return retVal;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SVGElementImpl::hasAttribute(const DOM::DOMString &name)
|
|
|
|
{
|
|
|
|
return m_attributes.find(name.string()) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SVGElementImpl::hasAttributes()
|
|
|
|
{
|
|
|
|
return m_attributes.count() > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVGElementImpl::setApplyAttribute(const TQString &name, const TQString &value)
|
|
|
|
{
|
|
|
|
if(hasAttribute(name))
|
|
|
|
{
|
|
|
|
TQString cur = getAttribute(name).string();
|
|
|
|
cur = cur.simplifyWhiteSpace();
|
|
|
|
|
|
|
|
if(!cur.endsWith(";"))
|
|
|
|
cur += "; ";
|
|
|
|
|
|
|
|
cur += value;
|
|
|
|
|
|
|
|
setAttribute(name, cur);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
setAttribute(name, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVGElementImpl::setId(DOM::DOMString id)
|
|
|
|
{
|
|
|
|
setAttribute("id", id);
|
|
|
|
|
|
|
|
if(ownerDoc() && ownerDoc()->rootElement() && !id.isEmpty())
|
|
|
|
ownerDoc()->rootElement()->addToIdMap(id.string(), this);
|
|
|
|
else if(m_ownerSVGElement && !id.isEmpty())
|
|
|
|
m_ownerSVGElement->addToIdMap(id.string(), this);
|
|
|
|
}
|
|
|
|
|
|
|
|
DOM::DOMString SVGElementImpl::id() const
|
|
|
|
{
|
|
|
|
return getAttribute("id");
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVGElementImpl::setXmlbase(DOM::DOMString xmlbase)
|
|
|
|
{
|
|
|
|
setAttribute("xml:base", xmlbase);
|
|
|
|
}
|
|
|
|
|
|
|
|
DOM::DOMString SVGElementImpl::xmlbase() const
|
|
|
|
{
|
|
|
|
return getAttribute("xml:base");
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVGElementImpl::setOwnerSVGElement(SVGSVGElementImpl *owner)
|
|
|
|
{
|
|
|
|
if(m_ownerSVGElement)
|
|
|
|
m_ownerSVGElement->deref();
|
|
|
|
|
|
|
|
m_ownerSVGElement = owner;
|
|
|
|
|
|
|
|
if(m_ownerSVGElement)
|
|
|
|
m_ownerSVGElement->ref();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVGElementImpl::setViewportElement(SVGElementImpl *viewport)
|
|
|
|
{
|
|
|
|
if(m_viewportElement)
|
|
|
|
m_viewportElement->deref();
|
|
|
|
|
|
|
|
m_viewportElement = viewport;
|
|
|
|
|
|
|
|
if(m_viewportElement)
|
|
|
|
m_viewportElement->ref();
|
|
|
|
}
|
|
|
|
|
|
|
|
SVGSVGElementImpl *SVGElementImpl::ownerSVGElement() const
|
|
|
|
{
|
|
|
|
return m_ownerSVGElement;
|
|
|
|
}
|
|
|
|
|
|
|
|
SVGElementImpl *SVGElementImpl::viewportElement() const
|
|
|
|
{
|
|
|
|
return m_viewportElement;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVGElementImpl::setAttributes(const TQXmlAttributes &attrs)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < attrs.length(); i++)
|
|
|
|
{
|
|
|
|
setAttribute(attrs.localName(i), attrs.value(i));
|
|
|
|
setAttributeInternal(attrs.localName(i), attrs.value(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
setAttributes();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVGElementImpl::setAttributes()
|
|
|
|
{
|
|
|
|
// Finalize style
|
|
|
|
SVGStylableImpl *style = dynamic_cast<SVGStylableImpl *>(this);
|
|
|
|
|
|
|
|
if(style)
|
|
|
|
style->processStyle();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVGElementImpl::setAttributes(bool deep)
|
|
|
|
{
|
|
|
|
// Finalize style
|
|
|
|
SVGStylableImpl *style = dynamic_cast<SVGStylableImpl *>(this);
|
|
|
|
|
|
|
|
if(style)
|
|
|
|
style->processStyle();
|
|
|
|
|
|
|
|
if(deep)
|
|
|
|
{
|
|
|
|
if(hasChildNodes())
|
|
|
|
{
|
|
|
|
DOM::Node n;
|
|
|
|
for(n = firstChild(); !n.isNull(); n = n.nextSibling())
|
|
|
|
{
|
|
|
|
SVGElementImpl *elem = ownerDoc()->getElementFromHandle(n.handle());
|
|
|
|
if(elem)
|
|
|
|
elem->setAttributes(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SVGElementImpl::prepareMouseEvent(const TQPoint &p, const TQPoint &a, SVGMouseEventImpl *mev)
|
|
|
|
{
|
|
|
|
SVGShapeImpl *shape = dynamic_cast<SVGShapeImpl *>(this);
|
|
|
|
if(shape)
|
|
|
|
return shape->prepareMouseEvent(p, a, mev);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SVGElementImpl::dispatchEvent(int id, bool canBubbleArg, bool cancelableArg)
|
|
|
|
{
|
|
|
|
SVGEventImpl *evt = new SVGEventImpl(static_cast<SVGEvent::EventId>(id), canBubbleArg, cancelableArg);
|
|
|
|
|
|
|
|
evt->ref();
|
|
|
|
bool ret = dispatchEvent(evt, true);
|
|
|
|
evt->deref();
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SVGElementImpl::dispatchEvent(SVGEventImpl *evt, bool tempEvent)
|
|
|
|
{
|
|
|
|
evt->setTarget(this);
|
|
|
|
|
|
|
|
// Find out, where to send to -> collect parent nodes
|
|
|
|
TQPtrList<SVGElementImpl> nodeChain;
|
|
|
|
|
|
|
|
for(DOM::Element e = *this; !e.isNull(); e = e.parentNode())
|
|
|
|
nodeChain.prepend(ownerDoc()->getElementFromHandle(e.handle()));
|
|
|
|
|
|
|
|
// Trigger any capturing event handlers on our way down
|
|
|
|
evt->setEventPhase(DOM::Event::CAPTURING_PHASE);
|
|
|
|
|
|
|
|
TQPtrListIterator<SVGElementImpl> it(nodeChain);
|
|
|
|
for(; it.current() && it.current() != this && !evt->propagationStopped(); ++it)
|
|
|
|
{
|
|
|
|
evt->setCurrentTarget(it.current());
|
|
|
|
|
|
|
|
if(it.current())
|
|
|
|
it.current()->handleLocalEvents(evt, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dispatch to the actual target node
|
|
|
|
it.toLast();
|
|
|
|
if(!evt->propagationStopped())
|
|
|
|
{
|
|
|
|
evt->setEventPhase(DOM::Event::AT_TARGET);
|
|
|
|
evt->setCurrentTarget(it.current());
|
|
|
|
|
|
|
|
if(it.current())
|
|
|
|
it.current()->handleLocalEvents(evt, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
--it;
|
|
|
|
|
|
|
|
// Bubble up again
|
|
|
|
if(evt->bubbles())
|
|
|
|
{
|
|
|
|
evt->setEventPhase(DOM::Event::BUBBLING_PHASE);
|
|
|
|
for(; it.current() && !evt->propagationStopped(); --it)
|
|
|
|
{
|
|
|
|
evt->setCurrentTarget(it.current());
|
|
|
|
|
|
|
|
if(it.current())
|
|
|
|
it.current()->handleLocalEvents(evt, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
evt->setCurrentTarget(0);
|
|
|
|
evt->setEventPhase(0); // I guess this is correct, the spec does not seem to say
|
|
|
|
// anything about the default event handler phase.
|
|
|
|
|
|
|
|
if(evt->bubbles())
|
|
|
|
{
|
|
|
|
// now we call all default event handlers (this is not part of DOM - it is internal to ksvg)
|
|
|
|
it.toLast();
|
|
|
|
for(; it.current() && !evt->propagationStopped() && !evt->defaultPrevented() && !evt->defaultHandled(); --it)
|
|
|
|
it.current()->defaultEventHandler(evt);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If tempEvent is true, this means that the DOM implementation will not be storing a reference to the event, i.e.
|
|
|
|
// there is no way to retrieve it from javascript if a script does not already have a reference to it in a variable.
|
|
|
|
// So there is no need for the interpreter to keep the event in its cache
|
|
|
|
if(tempEvent)
|
|
|
|
ownerDoc()->ecmaEngine()->finishedWithEvent(evt);
|
|
|
|
|
|
|
|
return !evt->defaultPrevented(); // ### what if defaultPrevented was called before dispatchEvent?
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SVGElementImpl::dispatchKeyEvent(TQKeyEvent *ke)
|
|
|
|
{
|
|
|
|
DOM::AbstractView temp;
|
|
|
|
|
|
|
|
SVGEvent::EventId evtId = SVGEvent::UNKNOWN_EVENT;
|
|
|
|
|
|
|
|
if(ke->type() == TQEvent::KeyRelease && !ke->isAutoRepeat())
|
|
|
|
evtId = SVGEvent::KEYUP_EVENT;
|
|
|
|
else if(ke->isAutoRepeat())
|
|
|
|
evtId = SVGEvent::KEYPRESS_EVENT;
|
|
|
|
else if(ke->type() == TQEvent::KeyPress)
|
|
|
|
evtId = SVGEvent::KEYDOWN_EVENT;
|
|
|
|
|
|
|
|
if(evtId == SVGEvent::KEYUP_EVENT && hasEventListener(SVGEvent::DOMACTIVATE_EVENT, false))
|
|
|
|
dispatchEvent(SVGEvent::DOMACTIVATE_EVENT, true, true);
|
|
|
|
|
|
|
|
if(!hasEventListener(evtId, false))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
SVGEventImpl *evt = new SVGKeyEventImpl(ke, temp, evtId);
|
|
|
|
|
|
|
|
evt->ref();
|
|
|
|
bool ret = dispatchEvent(evt, true);
|
|
|
|
evt->deref();
|
|
|
|
|
|
|
|
// Rerender now! Once! (Niko)
|
|
|
|
ownerDoc()->rerender();
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SVGElementImpl::dispatchMouseEvent(int id, bool canBubbleArg, bool cancelableArg, long detailArg, long screenXArg, long screenYArg, long clientXArg, long clientYArg, bool ctrlKeyArg, bool altKeyArg, bool shiftKeyArg, bool metaKeyArg, unsigned short buttonArg, SVGElementImpl *relatedTargetArg)
|
|
|
|
{
|
|
|
|
DOM::AbstractView temp;
|
|
|
|
|
|
|
|
SVGEventImpl *evt = new SVGMouseEventImpl(static_cast<SVGEvent::EventId>(id),
|
|
|
|
canBubbleArg, cancelableArg, temp, detailArg,
|
|
|
|
screenXArg, screenYArg,
|
|
|
|
clientXArg, clientYArg,
|
|
|
|
ctrlKeyArg, altKeyArg, shiftKeyArg, metaKeyArg,
|
|
|
|
buttonArg, relatedTargetArg);
|
|
|
|
|
|
|
|
evt->ref();
|
|
|
|
bool ret = dispatchEvent(evt, true);
|
|
|
|
evt->deref();
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVGElementImpl::setOwnerDoc(SVGDocumentImpl *doc)
|
|
|
|
{
|
|
|
|
if(m_ownerDoc)
|
|
|
|
m_ownerDoc->removeFromElemDict(handle());
|
|
|
|
|
|
|
|
m_ownerDoc = doc;
|
|
|
|
|
|
|
|
if(m_ownerDoc)
|
|
|
|
m_ownerDoc->addToElemDict(handle(), this);
|
|
|
|
}
|
|
|
|
|
|
|
|
SVGDocumentImpl *SVGElementImpl::ownerDoc() const
|
|
|
|
{
|
|
|
|
return m_ownerDoc;
|
|
|
|
}
|
|
|
|
|
|
|
|
SVGElementImpl *SVGElementImpl::cloneNode(bool deep)
|
|
|
|
{
|
|
|
|
DOM::Element impl = static_cast<DOM::Document *>(ownerDoc())->createElementNS("", tagName());
|
|
|
|
SVGElementImpl *newElement = SVGDocumentImpl::createElement(tagName(), impl.cloneNode(false), ownerDoc());
|
|
|
|
newElement->setOwnerSVGElement(ownerSVGElement());
|
|
|
|
newElement->setViewportElement(viewportElement());
|
|
|
|
|
|
|
|
SVGHelperImpl::copyAttributes(this, newElement);
|
|
|
|
|
|
|
|
// Recalc style
|
|
|
|
//newElement->setAttributes();
|
|
|
|
|
|
|
|
if(deep)
|
|
|
|
cloneChildNodes(newElement);
|
|
|
|
|
|
|
|
return newElement;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVGElementImpl::cloneChildNodes(SVGElementImpl *clone)
|
|
|
|
{
|
|
|
|
DOM::Node n;
|
|
|
|
for(n = firstChild(); !n.isNull(); n = n.nextSibling())
|
|
|
|
{
|
|
|
|
SVGElementImpl *elem = ownerDoc()->getElementFromHandle(n.handle());
|
|
|
|
if(elem)
|
|
|
|
clone->appendChild(*elem->cloneNode(true));
|
|
|
|
else if(n.nodeType() == DOM::Node::TEXT_NODE)
|
|
|
|
clone->appendChild(n.cloneNode(true));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVGElementImpl::gotError(const TQString &errorDesc)
|
|
|
|
{
|
|
|
|
if(ownerDoc())
|
|
|
|
{
|
|
|
|
ownerDoc()->finishParsing(true, errorDesc);
|
|
|
|
if(hasEventListener(SVGEvent::ERROR_EVENT, true))
|
|
|
|
dispatchEvent(SVGEvent::ERROR_EVENT, false, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString SVGElementImpl::collectText()
|
|
|
|
{
|
|
|
|
TQString text;
|
|
|
|
|
|
|
|
if(hasChildNodes())
|
|
|
|
{
|
|
|
|
DOM::Node node = firstChild();
|
|
|
|
|
|
|
|
for(; !node.isNull(); node = node.nextSibling())
|
|
|
|
{
|
|
|
|
if(node.nodeType() == DOM::Node::TEXT_NODE)
|
|
|
|
{
|
|
|
|
DOM::Text textNode = node;
|
|
|
|
text += textNode.data().string();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
|
|
|
// vim:ts=4:noet
|