/* * Copyright (c) 2007 Gustavo Pichorim Boiko * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "layoutmanager.h" #include "randr.h" #include "randrscreen.h" #include "randroutput.h" #include "outputgraphicsitem.h" #include #include LayoutManager::LayoutManager(RandRScreen *screen, QGraphicsScene *scene) : QObject(screen) { m_screen = screen; m_scene = scene; } LayoutManager::~LayoutManager() { } void LayoutManager::slotAdjustOutput(OutputGraphicsItem *output) { QPointF p = output->pos(); qreal nearest = m_scene->width() * m_scene->height(); OutputGraphicsItem *selected = NULL; OutputGraphicsItem *mouseGrabber = dynamic_cast(m_scene->mouseGrabberItem()); // find the nearest item QList itemList = m_scene->items(); foreach(QGraphicsItem *current, itemList) { OutputGraphicsItem *cur = dynamic_cast(current); if (cur == output || cur == mouseGrabber) { continue; } QPointF pos = cur->pos(); qreal distance = (p.x() - pos.x())*(p.x()-pos.x()) + (p.y() - pos.y())*(p.y() - pos.y()); if (distance <=nearest) { nearest = distance; selected = cur; } } if (selected) { // find in which side this QRectF s = selected->boundingRect(); QRectF i = output->boundingRect(); s.translate(selected->scenePos()); i.translate(output->scenePos()); // calculate the distances qreal top = qAbs(i.top() - s.bottom()); qreal bottom = qAbs(i.bottom() - s.top()); qreal left = qAbs(i.left() - s.right()); qreal right = qAbs(i.right() - s.left()); // choose top if (top <= bottom && top <= left && top <= right) { output->setTop(selected); selected->setBottom(output); } // choose bottom else if (bottom < top && bottom <= left && bottom <= right) { output->setBottom(selected); selected->setTop(output); } // choose left else if (left < top && left < bottom && left <= right) { output->setLeft(selected); selected->setRight(output); } // choose right else { output->setRight(selected); selected->setLeft(output); } } // now visit all the outputs on the screen to adjust their positions // starting by the item selected to be the parent of the current item QList visitedList; // FIXME: after adjusting the scene, we have to translate everything back to // the 0,0 position so that everything is onscreen output->setPos(0,0); // call a recursive function to adjust the outputs adjustScene(output, visitedList); } void LayoutManager::adjustScene(OutputGraphicsItem *current, QList &visited) { visited.append(current); OutputGraphicsItem *item; item = current->left(); if (item && visited.indexOf(item) == -1) { item->setPos(current->x() - item->boundingRect().width(), current->y()); adjustScene(item, visited); } item = current->right(); if (item && visited.indexOf(item) == -1) { item->setPos(current->x() + current->boundingRect().width(), current->y()); adjustScene(item, visited); } item = current->top(); if (item && visited.indexOf(item) == -1) { item->setPos(current->x(), current->y() - item->boundingRect().height()); adjustScene(item, visited); } item = current->bottom(); if (item && visited.indexOf(item) == -1) { item->setPos(current->x(), current->y() + current->boundingRect().height()); adjustScene(item, visited); } }