Move tiles on HomeWindow

More work to support moving tiles on HomeWindow. This update
adds tile movement and 'pushing' other tiles out the way as
you move them around.

Tile ordering/positioning is still todo, but this introduces
the visual feedback during a move for the user.
This commit is contained in:
Mark Liversedge
2011-01-08 20:06:29 +00:00
parent 6ac75fda3a
commit 4e2d6ef04c
4 changed files with 226 additions and 6 deletions

View File

@@ -99,6 +99,16 @@ bool GcWindow::resizable() const
return _resizable;
}
void GcWindow::setGripped(bool x)
{
_gripped = x;
}
bool GcWindow::gripped() const
{
return _gripped;
}
GcWindow::GcWindow()
{
}
@@ -251,8 +261,8 @@ GcWindow::mousePressEvent(QMouseEvent *e)
oHeightFactor = heightFactor();
oX = pos().x();
oY = pos().y();
mX = e->globalX();
mY = e->globalY();
mX = mapFromGlobal(QCursor::pos()).x();
mY = mapFromGlobal(QCursor::pos()).y();
setDragState(h); // set drag state then!
@@ -262,6 +272,20 @@ GcWindow::mousePressEvent(QMouseEvent *e)
void
GcWindow::mouseReleaseEvent(QMouseEvent *)
{
// tell the owner!
if (dragState == Move) {
setProperty("gripped", false);
emit moved(this);
} else if (dragState == Left ||
dragState == Right ||
dragState == Top ||
dragState == Bottom ||
dragState == TLCorner ||
dragState == TRCorner ||
dragState == BLCorner ||
dragState == BRCorner) {
emit resized(this);
}
setDragState(None);
repaint();
}
@@ -306,14 +330,15 @@ GcWindow::mouseMoveEvent(QMouseEvent *e)
}
// work out the relative move x and y
int relx = e->globalX() - mX;
int rely = e->globalY() - mY;
int relx = mapFromGlobal(QCursor::pos()).x() - mX;
int rely = mapFromGlobal(QCursor::pos()).y() - mY;
switch (dragState) {
default:
case Move :
move(oX + relx, oY + rely);
emit moving(this);
break;
case TLCorner :
@@ -325,6 +350,7 @@ GcWindow::mouseMoveEvent(QMouseEvent *e)
if (newWidth > 30 && newHeight > 30) {
move(oX + relx, oY + rely);
setNewSize(newWidth, newHeight);
emit resizing(this);
}
}
break;
@@ -338,6 +364,7 @@ GcWindow::mouseMoveEvent(QMouseEvent *e)
if (newWidth > 30 && newHeight > 30) {
move(oX, oY + rely);
setNewSize(newWidth, newHeight);
emit resizing(this);
}
}
break;
@@ -351,6 +378,7 @@ GcWindow::mouseMoveEvent(QMouseEvent *e)
if (newWidth > 30 && newHeight > 30) {
move(oX + relx, oY);
setNewSize(newWidth, newHeight);
emit resizing(this);
}
}
break;
@@ -363,6 +391,7 @@ GcWindow::mouseMoveEvent(QMouseEvent *e)
// need to move and resize
if (newWidth > 30 && newHeight > 30) {
setNewSize(newWidth, newHeight);
emit resizing(this);
}
}
break;
@@ -375,6 +404,7 @@ GcWindow::mouseMoveEvent(QMouseEvent *e)
if (newHeight > 30) {
move (oX, oY + rely);
setNewSize(oWidth, newHeight);
emit resizing(this);
}
}
break;
@@ -386,6 +416,7 @@ GcWindow::mouseMoveEvent(QMouseEvent *e)
// need to move and resize
if (newHeight > 30) {
setNewSize(oWidth, newHeight);
emit resizing(this);
}
}
break;
@@ -398,6 +429,7 @@ GcWindow::mouseMoveEvent(QMouseEvent *e)
if (newWidth > 30) {
move (oX + relx, oY);
setNewSize(newWidth, oHeight);
emit resizing(this);
}
}
break;
@@ -409,11 +441,14 @@ GcWindow::mouseMoveEvent(QMouseEvent *e)
// need to move and resize
if (newWidth > 30) {
setNewSize(newWidth, oHeight);
emit resizing(this);
}
}
break;
}
oX = pos().x();
oY = pos().y();
//repaint();
//QApplication::processEvents(); // flicker...
}
@@ -440,6 +475,7 @@ void
GcWindow::setDragState(DragState d)
{
dragState = d;
setProperty("gripped", dragState == Move ? true : false);
setCursorShape(d);
}

View File

@@ -70,6 +70,7 @@ private:
// can be resized
Q_PROPERTY(bool resizable READ resizable WRITE setResizable USER true);
Q_PROPERTY(bool gripped READ gripped WRITE setGripped);
QWidget *_controls;
QString _title;
@@ -79,6 +80,7 @@ private:
double _widthFactor;
double _heightFactor;
bool _resizable;
bool _gripped;
// we paint a heading if there is space in the top margin
void paintEvent (QPaintEvent * event);
@@ -96,6 +98,10 @@ signals:
void rideItemChanged(RideItem*);
void heightFactorChanged(double);
void widthFactorChanged(double);
void resizing(GcWindow*);
void moving(GcWindow*);
void resized(GcWindow*); // finished resizing
void moved(GcWindow*); // finished moving
public:
@@ -125,11 +131,17 @@ public:
void setResizable(bool);
bool resizable() const;
void setGripped(bool);
bool gripped() const;
GcWinID type() const { return _type; }
void setType(GcWinID x) { _type = x; } // only really used by the window registry
virtual bool amVisible();
// for sorting... we look at x
bool operator< (GcWindow right) const { return geometry().x() < right.geometry().x(); }
// mouse actions -- resizing and dragging tiles
bool eventFilter(QObject *object, QEvent *e);
virtual void mousePressEvent(QMouseEvent *);

View File

@@ -379,6 +379,12 @@ HomeWindow::addChart(GcWindow* newone)
// add to the list
charts.append(newone);
newone->hide();
// watch for moves etc
connect(newone, SIGNAL(resizing(GcWindow*)), this, SLOT(windowResizing(GcWindow*)));
connect(newone, SIGNAL(moving(GcWindow*)), this, SLOT(windowMoving(GcWindow*)));
connect(newone, SIGNAL(resized(GcWindow*)), this, SLOT(windowResized(GcWindow*)));
connect(newone, SIGNAL(moved(GcWindow*)), this, SLOT(windowMoved(GcWindow*)));
}
}
@@ -456,7 +462,7 @@ HomeWindow::resizeEvent(QResizeEvent *e)
- ((widthFactor-1) * 20) /* internal spacing */
) / widthFactor;
double newheight = (winArea->height()
double newheight = (winArea->height()
- 40 /* top and bottom marings */
- ((heightFactor-1) * 20) /* internal spacing */
) / heightFactor;
@@ -550,6 +556,167 @@ HomeWindow::eventFilter(QObject *object, QEvent *e)
return false;
}
void
HomeWindow::windowMoved(GcWindow*w)
{
}
void
HomeWindow::windowResized(GcWindow*w)
{
}
void
HomeWindow::windowMoving(GcWindow*w)
{
// ensure the mouse pointer is visible
QPoint pos = winWidget->mapFromGlobal(QCursor::pos());
winArea->ensureVisible(pos.x(), pos.y(), 20, 20);
// since the widget has moved, the mouse is no longer
// in the same position relevant to the widget, so
// move the mouse back to the same position relevant
// to the widget
QCursor::setPos(winWidget->mapToGlobal(pos));
// Move the other windows out the way...
for(int i=0; i<charts.count(); i++) {
if (charts[i] != w && !charts[i]->gripped() && charts[i]->geometry().intersects(w->geometry())) {
// shift whilst we move then
QRect inter = charts[i]->geometry().intersected(w->geometry());
// move left
if (charts[i]->geometry().x() < w->geometry().x()) {
int newx = inter.x() - 20 - charts[i]->geometry().width();
if (charts[i]->geometry().x() > newx)
charts[i]->move(newx, charts[i]->geometry().y());
} else {
int newx = inter.x()+inter.width() + 20;
if (charts[i]->geometry().x() < newx)
charts[i]->move(newx, charts[i]->geometry().y());
}
windowMoving(charts[i]); // move the rest...
}
}
// now if any are off the screen try and get them
// back on the screen without disturbing the other
// charts (unless they are off the screen too)
for(int i=0; i<charts.count(); i++) {
if (!charts[i]->gripped() && (charts[i]->x() < 20 || (charts[i]->x()+charts[i]->width()) > winArea->geometry().width())) {
// to the left...
if (charts[i]->geometry().x() < 20) {
QRect back(20, charts[i]->geometry().y(),
charts[i]->geometry().width(),
charts[i]->geometry().height());
// loop through the other charts and see
// how far it can sneak back on...
for(int j=0; j<charts.count(); j++) {
if (charts[j] != charts[i]) {
if (back.intersects(charts[j]->geometry())) {
QRect inter = back.intersected(charts[j]->geometry());
int newx = inter.x() - back.width() - 20;
if (back.x() > newx) {
back.setX(newx);
back.setWidth(charts[i]->width());
}
}
}
}
#if 0
// any space?
if (back.x() < 20) {
// we're still off screen so
// lets shift all the windows to the
// right if we can
QList<GcWindow*> obstacles;
QRect fback(20, charts[i]->geometry().y(),
charts[i]->geometry().width(),
charts[i]->geometry().height());
// order obstacles left to right
for(int j=0; j<charts.count(); j++) {
if (charts[j] != charts[i] &&
fback.intersects(charts[j]->geometry()))
obstacles.append(charts[j]);
qSort(obstacles);
}
// where to stop? all or is the
// gripped window in there
// or stop if offscreen already
int stop=0;
while (stop < obstacles.count()) {
if (obstacles[stop]->gripped() ||
(obstacles[stop]->geometry().x() + obstacles[stop]->width()) > winArea->width())
break;
stop++;
}
// at this point we know that members
// 0 - stop are possibly in our way
// we need to move the leftmost, if it
// fits we stop, if not we move the next one
// and the leftmost, then the next one
// until we have exhausted all candidates
// try again!
// loop through the other charts and see
// how far it can sneak back on...
back = QRect(20, charts[i]->geometry().y(),
charts[i]->geometry().width(),
charts[i]->geometry().height());
for(int j=0; j<charts.count(); j++) {
if (charts[j] != charts[i]) {
if (back.intersects(charts[j]->geometry())) {
QRect inter = back.intersected(charts[j]->geometry());
back.setX(inter.x()-back.width()-20);
}
}
}
}
#endif
charts[i]->move(back.x(), back.y());
} else {
QRect back(winArea->width() - charts[i]->width() - 20,
charts[i]->geometry().y(),
charts[i]->geometry().width(),
charts[i]->geometry().height());
// loop through the other charts and see
// how far it can sneak back on...
for(int j=0; j<charts.count(); j++) {
if (charts[j] != charts[i]) {
if (back.intersects(charts[j]->geometry())) {
QRect inter = back.intersected(charts[j]->geometry());
int newx = inter.x() + inter.width() + 20;
if (back.x() < newx) back.setX(newx);
}
}
}
// any space?
charts[i]->move(back.x(), back.y());
}
}
}
}
void
HomeWindow::windowResizing(GcWindow*w)
{
QPoint pos = this->mapFromGlobal(QCursor::pos());
winArea->ensureVisible(pos.x(), pos.y(), 20, 20);
}
GcWindowDialog::GcWindowDialog(GcWinID type, MainWindow *mainWindow) : mainWindow(mainWindow), type(type)
{
setAttribute(Qt::WA_DeleteOnClose);
@@ -830,4 +997,3 @@ bool ViewParser::endDocument()
{
return TRUE;
}

View File

@@ -70,6 +70,12 @@ class HomeWindow : public GcWindow
//notifiction that been made visible
void selected();
// moved or resized
void windowMoving(GcWindow*);
void windowResizing(GcWindow*);
void windowMoved(GcWindow*);
void windowResized(GcWindow*);
protected:
MainWindow *mainWindow;
bool active; // ignore gui signals when changing views