/*
* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 2.1 of the License.
*
* This program 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not,
* see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/".
*
* Description:
*
*/
#include <QList>
#include <QDebug>
#include <QGraphicsSceneContextMenuEvent>
#include "ChromeSnippet.h"
#include "WebChromeContainerSnippet.h"
#include "ChromeLayout.h"
#include "SlidingWidget.h"
#include "ViewController.h"
#include "ObjectCharm.h"
#include "bedrockprovisioning.h"
namespace GVA {
// -----------------------------
ChromeLayout::ChromeLayout(QGraphicsItem * parent, Qt::WindowFlags wFlags)
: QGraphicsWidget(parent, wFlags),
m_topBar(0),
m_bottomBar(0),
m_leftBar(0),
m_rightBar(0),
m_aspect(portrait),
m_bottomBarHeight(0)
{
m_layout = new QGraphicsAnchorLayout();
m_layout->setContentsMargins(0,0,0,0);
m_layout->setSpacing(0);
setLayout(m_layout);
addAnchors();
m_viewPort = new SlidingWidget(this);
m_layout->addAnchor(m_viewPort, Qt::AnchorTop, m_topBar, Qt::AnchorBottom);
m_layout->addAnchor(m_viewPort, Qt::AnchorBottom, m_bottomBar, Qt::AnchorTop);
m_layout->addAnchor(m_viewPort, Qt::AnchorLeft, m_leftBar, Qt::AnchorRight);
m_layout->addAnchor(m_viewPort, Qt::AnchorRight, m_rightBar, Qt::AnchorLeft);
}
ChromeLayout::~ChromeLayout()
{
delete m_bottomBar;
delete m_topBar;
delete m_leftBar;
delete m_rightBar;
delete m_viewPort;
}
void ChromeLayout::addAnchors(){
if (!m_bottomBar){
m_bottomBar = new QGraphicsWidget(this);
m_bottomBar->setPreferredHeight(0);
m_bottomBar->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
m_layout->addAnchor(m_bottomBar, Qt::AnchorBottom, m_layout, Qt::AnchorBottom);
m_layout->addAnchors(m_bottomBar, m_layout, Qt::Horizontal);
}
if (!m_topBar){
m_topBar = new QGraphicsWidget(this);
m_topBar->setPreferredHeight(0);
m_topBar->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
m_layout->addAnchor(m_topBar, Qt::AnchorTop, m_layout, Qt::AnchorTop);
m_layout->addAnchors(m_topBar, m_layout, Qt::Horizontal);
}
if (!m_leftBar){
m_leftBar = new QGraphicsWidget(this);
m_leftBar->setPreferredWidth(0);
m_leftBar->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred));
m_layout->addAnchor(m_leftBar, Qt::AnchorLeft, m_layout, Qt::AnchorLeft);
m_layout->addAnchors(m_leftBar, m_layout, Qt::Vertical);
}
if (!m_rightBar){
m_rightBar = new QGraphicsWidget(this);
m_rightBar->setPreferredWidth(0);
m_rightBar->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred));
m_layout->addAnchor(m_rightBar, Qt::AnchorRight, m_layout, Qt::AnchorRight);
m_layout->addAnchors(m_rightBar, m_layout, Qt::Vertical);
}
}
void ChromeLayout::resizeEvent(QGraphicsSceneResizeEvent *ev)
{
emit resizing(ev->newSize());
int aspect = m_aspect;
m_aspect = (ev->newSize().width() > ev->newSize().height())?landscape:portrait;
if (m_aspect != aspect) {
QString mode = (m_aspect == landscape ? "Landscape" : "Portrait");
emit aspectChanged(m_aspect);
}
QGraphicsWidget::resizeEvent(ev);
}
void ChromeLayout::addView(ControllableViewBase * controllableView){
if (controllableView->widget()) {
m_viewPort->setWindow(controllableView->widget());
controllableView->widget()->setFocusPolicy(Qt::ClickFocus); //NB: Is this needed? Does it break anything?
controllableView->widget()->setZValue(-1.0); //Make sure we are behind any center anchored snippets
}
}
void ChromeLayout::anchorToView(ChromeSnippet* snippet, const QString& where)
{
Q_UNUSED(where)
m_viewPort->attachItem(snippet->widget());
}
void ChromeLayout::detachFromView(ChromeSnippet* snippet, const QString& where)
{
Q_UNUSED(where)
m_viewPort->detachItem(snippet->widget());
}
void ChromeLayout::anchorTogether(ChromeSnippet * first, ChromeSnippet * second, qreal x, qreal y)
{
first->widget()->setParentItem(second->widget());
first->widget()->setPos(x,y);
}
void ChromeLayout::unAnchor(ChromeSnippet* snippet)
{
snippet->widget()->setParentItem(0);
snippet->widget()->setParentItem(this);
}
qreal ChromeLayout::shrinkView(qreal delta)
{
m_viewPort->setShrinkMax(bottomBarHeight());
return m_viewPort->shrink(delta);
}
qreal ChromeLayout::setViewSlide(qreal pos)
{
return m_viewPort->setSlide(pos);
}
qreal ChromeLayout::slideView(qreal delta)
{
return m_viewPort->slide(delta);
}
//Check to see if snippet has an anchor and lay it out accordingly.
//Otherwise snippets determine their own positions from html
void ChromeLayout::anchorSnippet(ChromeSnippet * snippet)
{
if (snippet->anchor() == anchorBottom){
if (snippet->hidesContent()){
m_layout->addAnchor(snippet->widget(), Qt::AnchorBottom, m_bottomBar, Qt::AnchorTop);
m_layout->addAnchor(snippet->widget(), Qt::AnchorHorizontalCenter, m_bottomBar, Qt::AnchorHorizontalCenter);
} else {
snippet->widget()->setParentItem(m_bottomBar);
snippet->widget()->setY(-snippet->anchorOffset());
}
}
else if (snippet->anchor() == anchorTop){
if (snippet->hidesContent()){
m_layout->addAnchor(snippet->widget(),Qt::AnchorTop, m_topBar, Qt::AnchorBottom);
m_layout->addAnchor(snippet->widget(), Qt::AnchorHorizontalCenter, m_topBar, Qt::AnchorHorizontalCenter);
}
else {
snippet->widget()->setParentItem(m_topBar);
snippet->widget()->setY(snippet->anchorOffset());
}
}
else if (snippet->anchor() == anchorLeft){
if (snippet->hidesContent())
m_layout->addAnchor(snippet->widget(),Qt::AnchorLeft, m_leftBar, Qt::AnchorRight);
else {
snippet->widget()->setParentItem(m_leftBar);
snippet->widget()->setX(snippet->anchorOffset());
}
}
else if (snippet->anchor() == anchorRight){
if (snippet->hidesContent())
m_layout->addAnchor(snippet->widget(),Qt::AnchorRight, m_rightBar, Qt::AnchorLeft);
else {
snippet->widget()->setParentItem(m_rightBar);
snippet->widget()->setX(-snippet->anchorOffset());
}
}
else if (snippet->anchor() == anchorCenter) {
snippet->widget()->setParentItem(m_viewPort);
snippet->widget()->setZValue(0.0);
QGraphicsAnchorLayout * vl = static_cast<QGraphicsAnchorLayout*>(m_viewPort->layout());
vl->addAnchor(snippet->widget(), Qt::AnchorVerticalCenter, vl, Qt::AnchorVerticalCenter);
vl->addAnchor(snippet->widget(), Qt::AnchorHorizontalCenter, vl, Qt::AnchorHorizontalCenter);
}
else if (snippet->anchor() == anchorTopLeft){
m_layout->addCornerAnchors(snippet->widget(), Qt::TopLeftCorner, m_layout, Qt::TopLeftCorner);
}
else if (snippet->anchor() == anchorTopRight)
m_layout->addCornerAnchors(snippet->widget(), Qt::TopRightCorner, m_layout, Qt::TopRightCorner);
else if (snippet->anchor() == anchorBottomLeft)
m_layout->addCornerAnchors(snippet->widget(), Qt::BottomLeftCorner, m_layout, Qt::BottomLeftCorner);
else if (snippet->anchor() == anchorBottomRight)
m_layout->addCornerAnchors(snippet->widget(), Qt::BottomRightCorner, m_layout, Qt::BottomRightCorner);
}
void ChromeLayout:: addSnippet(ChromeSnippet * snippet, ChromeSnippet * container )
{
snippet->widget()->setParentItem(this);
if (container){
container->addChild(snippet);
}
anchorSnippet(snippet);
}
// Call after a snippet changes to visible state
void ChromeLayout::snippetShown(ChromeSnippet * snippet)
{
if (snippet->hidesContent()) {
if (snippet->anchor() == anchorBottom) {
/* snippet->widget()->size().height() is zero for WebChromeContainerSnippet
when default visible container snippet is shown, get ownerArea height instead */
WebChromeContainerSnippet * s = dynamic_cast<WebChromeContainerSnippet *>(snippet);
if (!s) {
m_bottomBarHeight = snippet->widget()->size().height();
}
else {
m_bottomBarHeight = s->ownerArea().height();
}
}
return;
}
if (snippet->anchor() == anchorBottom)
m_bottomBar->setPreferredHeight(m_bottomBar->preferredHeight() + snippet->widget()->preferredHeight());
else if (snippet->anchor() == anchorTop)
m_topBar->setPreferredHeight(m_topBar->preferredHeight() + snippet->widget()->preferredHeight());
else if (snippet->anchor() == anchorLeft){
m_leftBar->setPreferredWidth(m_leftBar->preferredWidth() + snippet->widget()->preferredWidth());
}
else if (snippet->anchor() == anchorRight){
m_rightBar->setPreferredWidth(m_rightBar->preferredWidth() + snippet->widget()->preferredWidth());
}
}
// Call before a snippet changes to invisible state
void ChromeLayout::snippetHiding(ChromeSnippet * snippet)
{
if (snippet->hidesContent())
return;
if (snippet->anchor() == anchorBottom)
m_bottomBar->setPreferredHeight(m_bottomBar->preferredHeight() - snippet->widget()->preferredHeight());
else if (snippet->anchor() == anchorTop)
m_topBar->setPreferredHeight(m_topBar->preferredHeight() - snippet->widget()->preferredHeight());
else if (snippet->anchor() == anchorLeft){
m_leftBar->setPreferredWidth(m_leftBar->preferredWidth() - snippet->widget()->preferredWidth());
}
else if (snippet->anchor() == anchorRight){
m_rightBar->setPreferredWidth(m_rightBar->preferredWidth() - snippet->widget()->preferredWidth());
}
}
QString ChromeLayout::getDisplayMode() const {
return (m_aspect==portrait)?"portrait":"landscape";
}
void ChromeLayout::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
{
event->accept();
}
//NB: Deprecate. This really shouldn't be necessary: anchor bars should be implemented as an expanding
//widget class.
void ChromeLayout::adjustAnchorOffset(ChromeSnippet * snippet, qreal delta)
{
if (snippet->anchor() == anchorBottom)
m_bottomBar->setPreferredHeight(m_bottomBar->preferredHeight() + delta);
else if (snippet->anchor() == anchorTop)
m_topBar->setPreferredHeight(m_topBar->preferredHeight() + delta);
else if (snippet->anchor() == anchorLeft){
m_leftBar->setPreferredWidth(m_leftBar->preferredWidth() + delta);
}
else if (snippet->anchor() == anchorRight){
m_rightBar->setPreferredWidth(m_rightBar->preferredWidth() + delta);
}
}
void ChromeLayout::setScene(QGraphicsScene *scene)
{
m_scene = scene;
//This is the root of the scene hierarchy
m_scene->addItem(this);
// For testing, turn on red dot that appears in response to various mouse events.
if(BEDROCK_PROVISIONING::BedrockProvisioning::createBedrockProvisioning()->valueAsInt("EnableTouchCircle", false)) {
new TouchCircleCharm(m_scene, this);
}
}
QSize ChromeLayout::viewPortSize(bool withoutTop ){
return (m_viewPort->viewPortSize(withoutTop));
}
} // endof namespace GVA