summaryrefslogtreecommitdiffstats
path: root/src/server/mainwindow/mainwindow.cpp
diff options
context:
space:
mode:
authorChristian Klinger2016-05-02 16:16:29 +0200
committerChristian Klinger2016-05-02 16:16:29 +0200
commitf8f3dae11294508355ca024cacb966f129c1c85c (patch)
treef6fe2291373800adeada224a039c60188c611bd2 /src/server/mainwindow/mainwindow.cpp
parentadded background-image loading. (diff)
downloadpvs2-f8f3dae11294508355ca024cacb966f129c1c85c.tar.gz
pvs2-f8f3dae11294508355ca024cacb966f129c1c85c.tar.xz
pvs2-f8f3dae11294508355ca024cacb966f129c1c85c.zip
better behaviour when placing a client symbol on top of another.
Diffstat (limited to 'src/server/mainwindow/mainwindow.cpp')
-rw-r--r--src/server/mainwindow/mainwindow.cpp178
1 files changed, 111 insertions, 67 deletions
diff --git a/src/server/mainwindow/mainwindow.cpp b/src/server/mainwindow/mainwindow.cpp
index 9f667a6..32d5186 100644
--- a/src/server/mainwindow/mainwindow.cpp
+++ b/src/server/mainwindow/mainwindow.cpp
@@ -38,6 +38,8 @@
#include "ui_mainwindow.h"
#include "ui_reloadroom.h"
+#include <vector>
+
#define sStrTutorNdef MainWindow::tr("No tutor defined.")
#define sStrTutorOffline MainWindow::tr("Tutor is offline.")
#define sStrSourceNdef MainWindow::tr("Please select a projection source.")
@@ -48,6 +50,8 @@
#define sStrClientOnline MainWindow::tr("Selected client is currently online.")
#define sStrNoDestAv MainWindow::tr("No projection destination available.")
+using std::vector;
+
/***************************************************************************//**
* Initialize MainWindow and ListenServer.
* @param ipListUrl
@@ -165,57 +169,77 @@ MainWindow::~MainWindow()
delete ui;
}
+/** Euclidean distance (why is this not implemented in QPoint?) */
+float distance(QPoint a, QPoint b) {
+ int dx = a.x() - b.x();
+ int dy = a.y() - b.y();
+ int sum = dx*dx + dy*dy;
+ return sqrt((float) sum);
+}
/***************************************************************************//**
- * Place the frames at possible Position.
- * If current position out of range, place frame into next free cell.
+ * Place the frame into a free position that is closest (Euclidean distance) to
+ * the preferred point.
+ *
+ * If current position out of range, place frame into the closest free cell.
+ * 'Algorithm': ideally, go in circles around the preferred point until you find
+ * a free spot. Lazy way: store all free positions in an array and find later
+ * there the closest (<- that's what I do)
+ *
* @param frame
*/
-void MainWindow::placeFrameInFreeSlot(ConnectionFrame* frame)
+void MainWindow::placeFrameInFreeSlot(ConnectionFrame* frame, QPoint preferred)
{
- // Get occupied cell of each frame and store status in an array
- const int elems = _tilesX * _tilesY;
- int currentIndex = 0;
- bool grid[elems];
- memset(grid, 0, sizeof(bool) * elems); // set everything to false
+ qDebug() << "placeFrameInFreeSlot(preferred = " << preferred << ")";
+ const QSize& clientSize = Global::getRooms()[Global::getCurrentRoom()]->clientSize;
+ /* Get occupied cell of each frame and store status in an array */
+ bool grid[_tilesX][_tilesY];
+ memset(grid, 0, sizeof(bool) * _tilesX * _tilesY); // set everything to false
+
+ /* fill grid */
for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it)
{
- const QPoint &oldpos = (*it)->frameGeometry().topLeft();
- const int tx = oldpos.x() / getTileWidthPx();
- const int ty = oldpos.y() / getTileHeightPx();
- const int index = tx + ty * _tilesX;
- if (frame == *it)
- {
- // Current frame is the frame to place, remember its old index
- currentIndex = index;
- continue;
- }
- if (index < 0 || index >= elems)
- {
- // Current frame is out of bounds, place in top left corner
- qDebug("Move A");
- (*it)->move(0, 0);
- grid[0] = true;
- continue;
- }
- // Just mark cell as occupied in array
- grid[index] = true;
- }
- // Safety
- if (currentIndex < 0 || currentIndex >= elems)
- currentIndex = 0;
- // Now place in next free cell, start looking at current position of frame
- for (int i = 0; i < elems; ++i)
- {
- const int index = (i + currentIndex) % elems;
- if (grid[index])
- continue;
- const int x = (index % _tilesX) * getTileWidthPx();
- const int y = (index / _tilesX) * getTileHeightPx();
- //qDebug() << "Index=" << index << " i=" << i << " cI=" << currentIndex << " elems=" << elems << " x=" << x << " y=" << y;
- qDebug("Move B");
- frame->move(x, y);
- break;
- }
+ const QPoint& position = (*it)->getGridPosition();
+
+ for (int x = position.x(); x < position.x() + clientSize.width(); x++) {
+ for (int y = position.y(); y < position.y() + clientSize.height(); y++) {
+ grid[x][y] = true;
+ }
+ }
+ }
+
+ /* Now place in next free cell, start looking at current position of frame */
+ vector<QPoint> freePositions;
+ for (int x = 0; x < _tilesX - clientSize.width(); x++) {
+ for ( int y = 0; y < _tilesY - clientSize.height(); y++) {
+ /* check if (x,y) is free */
+ bool isFree = true;
+ for (int dx = 0; dx < clientSize.width(); dx++) {
+ for (int dy = 0; dy < clientSize.width(); dy++) {
+ if (grid[x + dx][y + dy]) {
+ isFree = false;
+ }
+ }
+ }
+ if (isFree) {
+ QPoint freePos(x,y);
+ freePositions.push_back(freePos);
+ }
+ }
+ }
+ /* among all the free positions, find the closest */
+ float min_distance = 10000;
+ QPoint bestPosition = QPoint(-1, -1);
+
+ for (QPoint freePos : freePositions) {
+ float dist = distance(freePos, preferred);
+ if (dist < min_distance) {
+ min_distance = dist;
+ bestPosition = freePos;
+ }
+ }
+ frame->setGridPosition(bestPosition);
+ QPoint freePosPx(bestPosition.x() * getTileWidthPx(), bestPosition.y() * getTileHeightPx());
+ frame->setCurrentPosition(freePosPx);
}
/***************************************************************************//**
@@ -227,7 +251,10 @@ void MainWindow::placeFrameInFreeSlot(ConnectionFrame* frame)
ConnectionFrame* MainWindow::createFrame()
{
// Allocate and resize
- ConnectionFrame *cf = new ConnectionFrame(ui->frmRoom, getTileWidthPx(), getTileHeightPx());
+ int width = getTileWidthPx() * Global::getRooms()[Global::getCurrentRoom()]->clientSize.width();
+ int height= getTileHeightPx() * Global::getRooms()[Global::getCurrentRoom()]->clientSize.height();
+
+ ConnectionFrame *cf = new ConnectionFrame(ui->frmRoom, width, height);
_clientFrames.append(cf);
cf->show();
connect(cf, SIGNAL(frameMoved(bool, ConnectionFrame *)), this, SLOT(onPlaceFrame(bool, ConnectionFrame *)));
@@ -647,45 +674,60 @@ void MainWindow::reset()
*/
void MainWindow::onTutorListDownloaded(QByteArray& tutorList)
{
- // qDebug() << tutorList;
QString data = QString::fromUtf8(tutorList.constData(), tutorList.size());
_tutorList = data.split(QRegExp("[\r\n]"),QString::SkipEmptyParts);
qDebug() << _tutorList;
}
+
/***************************************************************************//**
- * Place Frame to from user specified position.
- * @param frame
+* Place Frame to from user specified position.
+* Behaviour: If placed exactly on another frame: replace that frame and place it
+* on the closest free slot. Otherwise: place connectionFrame on the closest free
+* slot.
*/
-void MainWindow::onPlaceFrame(bool activateTrash, ConnectionFrame* frame)
+void MainWindow::onPlaceFrame(bool activateTrash, ConnectionFrame* connectionFrame)
{
if (_tilesX <= 0 || _tilesY <= 0)
return;
- const QPoint &p = frame->frameGeometry().center();
- const QSize &s = ui->frmRoom->geometry().size();
- int x = (p.x() / getTileWidthPx()) * getTileWidthPx();
- int y = (p.y() / getTileHeightPx()) * getTileHeightPx();
+ const QPoint &p = connectionFrame->frameGeometry().center();
+ const QSize &s = ui->frmRoom->geometry().size();
+ /* round to grid */
+ int x = p.x() / getTileWidthPx();
+ int y = p.y() / getTileHeightPx();
if (x < 0)
x = 0;
else if (x > s.width() - getTileWidthPx())
- x = (_tilesX - 1) * getTileWidthPx();
+ x = (_tilesX - 1);
if (y < 0)
y = 0;
else if (y > s.height() - getTileHeightPx())
- y = (_tilesY - 1) * getTileHeightPx();
-
- frame->move(x, y);
- savePosition(frame);
- const QPoint &newpos = frame->frameGeometry().topLeft();
- for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it)
- {
- if (*it == frame)
- continue;
- if ((*it)->frameGeometry().topLeft() == newpos)
- {
- placeFrameInFreeSlot(*it);
+ y = (_tilesY - 1);
+ /* --- */
+
+ QPoint newPos(x,y);
+ connectionFrame->setGridPosition(newPos);
+ placeFrameInFreeSlot(connectionFrame, newPos);
+
+ /* if there is already a frame at that position, push it away */
+ bool replacedFrame = false;
+ for (auto it = _clientFrames.begin(); it != _clientFrames.end(); ++it) {
+ if (*it == connectionFrame) { continue; }
+
+ if ((*it)->getGridPosition() == newPos) {
+ connectionFrame->setGridPosition(newPos);
+ placeFrameInFreeSlot(*it, newPos); /* place frame in free slot, close to newPos */
+ replacedFrame = true;
+ break;
}
}
+ if (!replacedFrame) {
+ placeFrameInFreeSlot(connectionFrame, newPos);
+ }
+ /* update positions */
+
+ savePosition(connectionFrame); /* save in local config to remember position */
+ resizeEvent(NULL);
}
/***************************************************************************//**
@@ -1258,7 +1300,9 @@ void MainWindow::onClientAuthenticated(Client* client)
// Assign client instance
cf->assignClient(client);
+ resizeEvent(NULL); // This is where all the positioning should be
tellClientCurrentSituation(client);
+
}
/***************************************************************************//**