ginebra/chromesnippet.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 04 May 2010 12:39:35 +0300
changeset 0 1450b09d0cfd
permissions -rw-r--r--
Revision: 201015 Kit: 201018

/*
* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/


#include "chromesnippet.h"
#include "chromesnippetjsobject.h"
#include "chromewidget.h"
#include "graphicsitemanimation.h"
#include "scriptobjects.h"

#include <QGraphicsLinearLayout>
#include <QGraphicsSceneContextMenuEvent>
#include <QImage>
#include <QPainter>
#include "qwebframe.h"
#include "qwebpage.h"
#include "chromeview.h"

bool ChromeSnippet::contextMenuFlag = false;

ChromeSnippet::ChromeSnippet(QGraphicsItem * parent, ChromeWidget * owner, QObject *jsParent, const QString &docElementId)
  : QGraphicsRectItem(parent),
    m_owner(owner),
    m_docElementId(docElementId),
    m_layout(0),
    m_visibilityAnimator(0),
    m_attentionAnimator(0),
    m_dragging(false),
    m_draggable(false),
    m_anchor("AnchorNone"),
    m_anchorOffset(0),
    m_hidesContent(false),
    m_isHiding(false),
    m_jsObject(new ChromeSnippetJSObject(jsParent, *this, docElementId))
{
	  // Prevent hover events from passing through to the underlying widget.
    setAcceptHoverEvents(true);
}

ChromeSnippet::~ChromeSnippet()
{
  //qDebug() << "ChromeSnippet::~ChromeSnippet: " << m_docElementId;
  if(m_visibilityAnimator)
    delete m_visibilityAnimator;
  if(m_attentionAnimator)
    delete m_attentionAnimator;
  if(m_jsObject)
    delete m_jsObject;
}

void ChromeSnippet::setOwnerArea(const QRectF& ownerArea)
{
  m_ownerArea = ownerArea; 
}

QRectF& ChromeSnippet::ownerArea(){
  return m_ownerArea;
}

void ChromeSnippet::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
{
  Q_UNUSED(option)
  Q_UNUSED(widget)

  //qDebug() << "ChromeSnippet::paint: " << m_docElementId << " " << m_ownerArea;
  //If this snippet has no children, draw the snippet. Otherwise let the children draw themselves.
  // NB: Make this behavior configurable?
  if(childItems().isEmpty()){
#ifdef Q_OS_SYMBIAN
  painter->drawPixmap(QPoint(0, 0), *m_owner->buffer(), m_ownerArea);
#else
  painter->drawImage(QPoint(0, 0), *m_owner->buffer(), m_ownerArea);
#endif
  }
}

void ChromeSnippet::updateChildGeometries()
{
  //NB: layouts should be usable here, but the behavior
  //is weird. Investigage further.
  /* delete m_layout;
  m_layout = new QGraphicsLinearLayout();
  QList<QGraphicsItem*> children = childItems();
  for(int i = 0; i < children.size(); i++){
    ChromeSnippet * child = dynamic_cast<ChromeSnippet*>(children[i]);
    m_layout->addItem(child);
  }
  setLayout(m_layout);
  */
  // For now just lay out in a row according to the html layout
  
        
  QList<QGraphicsItem*> children = childItems();
  for(int i = 0; i < children.size(); i++){
    ChromeSnippet * child = dynamic_cast<ChromeSnippet*>(children[i]);  
  	child->setPos(child->ownerArea().x(), 0);
  }
  
  if((docElementId() == "ContextMenuBgId") || (docElementId() == "ContextMenuId")) // hide context menu
  {
  	hide();  			
  }
  
  	  
}
bool ChromeSnippet::getContextMenuFlag()
{
	return contextMenuFlag;
}

void ChromeSnippet::mousePressEvent(QGraphicsSceneMouseEvent * ev)
{
  // qDebug() << "ChromeSnippet::mousePressEvent: " << scene()->focusItem();
  // qDebug() << "ChromeSnippet::mousePressEvent: " << docElementId() << m_ownerArea << ev->pos();
  
  
  QRect qr = m_owner->getDocElementRect("contextMenuButton");  
  ChromeSnippet *cmsn = m_owner->getSnippet("ContextMenuId");	
   
  qreal qx = ev->pos().x();
  qreal qy = ev->pos().y();
  bool cmVisibility = cmsn->isVisible();

  if(!cmVisibility)
  	contextMenuFlag = false;
  else  if(qx >= qr.left() && qx <= qr.right() && (docElementId() == "WebViewToolbarId"))
  {
  		contextMenuFlag = true;  		
  		return;
  }
  
  
  contextMenuFlag = false;
  
  passMouseEventToPage(QEvent::MouseButtonPress, ev);
  m_owner->chromePage()->view()->setFocus();
  
  if(docElementId() == "ContextMenuBgId")
  {
  	ChromeSnippet *sn = m_owner->getSnippet("ContextMenuId");	
  	if(sn)
  		sn->hide();
  	hide();
  }
  else if(docElementId() != "ContextMenuId")
  {
  	ChromeSnippet *sn = m_owner->getSnippet("ContextMenuId");	
  	if(sn)
  		sn->hide();
  	ChromeSnippet *sn2 = m_owner->getSnippet("ContextMenuBgId");	
  	if(sn2)
  		sn2->hide();
  	
  }
 
  ev->accept();

  //FIXME hide the Suggests snippet or not
  ChromeSnippet* ssn = m_owner->getSnippet("SuggestsId");
  if (ssn && ssn->isVisible()) {
      if (docElementId() == "SuggestsId") {
          if (m_ownerArea.height() < ev->pos().y())
              hide();
      }
      else
          ssn->hide();
  }
}

void ChromeSnippet::mouseReleaseEvent(QGraphicsSceneMouseEvent * ev)
{
	
  if(m_dragging) {
    emit m_jsObject->dragFinished();
    m_dragging = false;
  }
  passMouseEventToPage(QEvent::MouseButtonRelease, ev);
}


void ChromeSnippet::mouseMoveEvent(QGraphicsSceneMouseEvent * ev)
{
  if(m_draggable) {
      if(!m_dragging) {
          m_dragging = true;
          emit m_jsObject->dragStarted();
      }
      moveBy((ev->pos()-ev->lastPos()).x(),(ev->pos()-ev->lastPos()).y());
  }
  else {
      passMouseEventToPage(QEvent::MouseMove, ev);
  }
}


void ChromeSnippet::mouseDoubleClickEvent(QGraphicsSceneMouseEvent * ev)
{
  passMouseEventToPage(QEvent::MouseButtonDblClick, ev);
  if(m_owner && m_owner->chromePage())
      m_owner->chromePage()->view()->setFocus();
}

void ChromeSnippet::passMouseEventToPage(QEvent::Type type, QGraphicsSceneMouseEvent *ev) {
  ev->accept();
  if(m_owner && m_owner->chromePage()) {
      // Translate the mouse press to the owner's coords and forward to owner page
      QMouseEvent shiftedEv( type, QPoint(int(m_ownerArea.x()), int(m_ownerArea.y()))+ev->pos().toPoint(),
                             ev->button(), ev->buttons(), ev->modifiers() );
    
      //qDebug() << "ChromeSnippet::passMouseEventToPage: " << shiftedEv.pos() << " " << &shiftedEv;
      m_owner->chromePage()->event(&shiftedEv);
  }
}

void ChromeSnippet::hoverMoveEvent(QGraphicsSceneHoverEvent *event ) {
  // Translate to a mouse move event.
  QMouseEvent shiftedEv( QEvent::MouseMove, QPoint(int(m_ownerArea.x()), int(m_ownerArea.y()))+event->pos().toPoint(),
                         Qt::NoButton, Qt::NoButton, Qt::NoModifier);
  if(m_owner && m_owner->chromePage())
        m_owner->chromePage()->event(&shiftedEv);
}

void ChromeSnippet::keyPressEvent ( QKeyEvent * event ) {
  event->accept();
  QApplication::sendEvent(m_owner->chromePage()->view(), event);
}

void ChromeSnippet::keyReleaseEvent ( QKeyEvent * event ) {
  event->accept();
  QApplication::sendEvent(m_owner->chromePage()->view(), event);
}

void ChromeSnippet::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) 
{
    event->accept();
}

void ChromeSnippet::setVisibilityAnimator(const QString& animatorName)
{
  setVisibilityAnimator(VisibilityAnimator::create(animatorName, this));
}

void ChromeSnippet::setAttentionAnimator(const QString& animatorName)
{
  setAttentionAnimator(AttentionAnimator::create(animatorName, this));
}

void ChromeSnippet::toggleVisibility()                    
{
  m_isHiding = (m_isHiding)?false:true;

  if(m_isHiding)
    emit m_jsObject->onHide();
  if(m_visibilityAnimator){
    emit m_jsObject->dragStarted();
    m_visibilityAnimator->toggleVisibility();
    emit m_jsObject->dragFinished();
  }
  else {
    (m_isHiding)?QGraphicsRectItem::hide():QGraphicsRectItem::show();
  }
  if(!m_isHiding)
      emit m_jsObject->onShow();
}

void ChromeSnippet::show(bool useAnimation){
  if(m_isHiding){
    if(useAnimation)
      toggleVisibility();
    else{
      QGraphicsRectItem::show();
      m_isHiding = false;
      emit m_jsObject->onShow();
    }
  }
}

void ChromeSnippet::hide(bool useAnimation){
  if(!m_isHiding){
    if(useAnimation)
      toggleVisibility();
    else{
      QGraphicsItem::hide();
      m_isHiding = true;
      emit m_jsObject->onHide();
    }
  }
}

void ChromeSnippet::toggleAttention()                    
{
  qDebug() << "ChromeSnippet::toggleAttention";
  if(m_attentionAnimator){
    m_attentionAnimator->toggleActive();
  }
}

QObject *ChromeSnippet::animate(int duration) {
  GraphicsItemAnimation *an = new GraphicsItemAnimation(this, duration);
  m_owner->chromePage()->mainFrame()->addToJavaScriptWindowObject("animation", an, QScriptEngine::ScriptOwnership);
  return an;
}

QObject *ChromeSnippet::getGeometry() const {
    ScriptRectF *r = new ScriptRectF(rect());
    m_owner->chromePage()->mainFrame()->addToJavaScriptWindowObject("rectf", r, QScriptEngine::ScriptOwnership);
    return r;
}

QObject *ChromeSnippet::getPosition() const {
    ScriptPoint *result = new ScriptPoint(pos().toPoint());
    m_owner->chromePage()->mainFrame()->addToJavaScriptWindowObject("point", result, QScriptEngine::ScriptOwnership);
    return result;
}

void ChromeSnippet::resize(qreal width, qreal height) {
    QRectF r = rect();
    r.setWidth(width);
    r.setHeight(height);
    setRect(r);
}

void ChromeSnippet::repaint() {
    //qDebug() << __func__ << "Area: " <<  m_ownerArea  << "Id " <<  m_docElementId;  
  m_owner->repaintRequested(m_ownerArea.toRect());
}

void ChromeSnippet::dump() const{
  qDebug() << "ChromeSnippet::dump: id=" << m_docElementId << " name=" << m_docElementName;
  qDebug() << "                     this=" << this;
  qDebug() << "                     pos()=" << pos();
  qDebug() << "                     rect()=" << rect();
  qDebug() << "                     m_ownerArea=" << m_ownerArea;
  qDebug() << "                     visible=" << isVisible();
  qDebug() << "                     zValue=" << zValue();
  if(parentObject())
      qDebug() << "                     parent=" << parentObject();
  if(parentWidget())
      qDebug() << "                     parentItem=" << parentWidget();
}

QObject *ChromeSnippet::getJSObject() { 
    return static_cast<QObject*>(m_jsObject); 
}

QString  ChromeSnippet::getDisplayMode()
{
	return m_owner->getDisplayMode();
	
	
}
/*
bool ChromeSnippet::sceneEventFilter ( QGraphicsItem * watched, QEvent * event ) {
    qDebug() << "ChromeSnippet::sceneEventFilter: " << event;
    return QGraphicsItem::sceneEventFilter(watched, event);
}
*/