Make Windows attached to the Mainwindow snap to Windows they get near and move the mainwindow accordingly
This commit is contained in:
parent
553138578d
commit
989d699372
3 changed files with 157 additions and 96 deletions
|
@ -92,35 +92,52 @@ BaseWindow::mouseMoveEvent (QMouseEvent *event)
|
|||
}
|
||||
|
||||
QPoint
|
||||
BaseWindow::snapWindow(QPoint pos, QWidgetList ignore)
|
||||
BaseWindow::snapWindow(QPoint pos, AttachedWindowMap attached)
|
||||
{
|
||||
//TODO: make snapdistance configurable
|
||||
qint32 snapdistance = 10;
|
||||
|
||||
qint32 left = pos.x ();
|
||||
qint32 right = left + width ();
|
||||
qint32 top = pos.y ();
|
||||
qint32 bottom = top + height ();
|
||||
|
||||
QWidgetList widgets = qApp->topLevelWidgets ();
|
||||
QWidget *w;
|
||||
// ignore widgets, MainWindow needs this for attached Widgets
|
||||
if (!ignore.isEmpty ()) {
|
||||
foreach (w, ignore) {
|
||||
int i = widgets.indexOf (w);
|
||||
BaseWindow *b;
|
||||
widgets.removeAt (widgets.indexOf (this));
|
||||
// ignore attached widgets
|
||||
// attached Widgets touch this window, and would create a strange movement
|
||||
if (!attached.isEmpty ()) {
|
||||
foreach (b, attached.keys ()) {
|
||||
int i = widgets.indexOf (b);
|
||||
if (i >= 0) {
|
||||
widgets.removeAt (i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool vSnapped = false;
|
||||
bool hSnapped = false;
|
||||
|
||||
attached.insert (this, QPoint (0,0));
|
||||
BaseWindow *ref;
|
||||
|
||||
// equalizerwindow and playlistwindow have only process this method once
|
||||
// the ugly part comes into play, because mainwindow also snaps to
|
||||
// windows it's subwindows get near.
|
||||
// We iterate over the moved window and all it's attached windows.
|
||||
// if a attached window can snap to a window, we use the offset of
|
||||
// this windows position to the mainwindow to calculate the position
|
||||
// we have to move the mainwindow to.
|
||||
//
|
||||
// As soon as we have a horizontal an vertical postition where the
|
||||
// windows can snap to, we stop further processing
|
||||
// (vSnapped and hSnapped are used to keep track of that)
|
||||
foreach (ref, attached.keys ()) {
|
||||
qint32 left = pos.x () + attached[ref].x ();
|
||||
qint32 right = left + ref->width ();
|
||||
qint32 top = pos.y () + attached[ref].y ();
|
||||
qint32 bottom = top + ref->height ();
|
||||
|
||||
QWidget *w;
|
||||
|
||||
// snap to left or right edge
|
||||
bool snappedV = false;
|
||||
bool snappedH = false;
|
||||
foreach (w, widgets) {
|
||||
if (w == this) {
|
||||
continue;
|
||||
}
|
||||
if (!w->isVisible ()) {
|
||||
continue;
|
||||
}
|
||||
|
@ -138,64 +155,103 @@ BaseWindow::snapWindow(QPoint pos, QWidgetList ignore)
|
|||
|
||||
// test if this widget can snap left or right to another widget
|
||||
// and if it can, test if the tops or bottoms can also snap
|
||||
if (!snappedV && (qAbs (w_left - right) < snapdistance)) {
|
||||
pos.setX (w_left - width ());
|
||||
snappedV = true;
|
||||
if (snappedH) {
|
||||
if (!vSnapped && (qAbs (w_left - right) < snapdistance)) {
|
||||
pos.setX (w_left - ref->width () - attached[ref].x ());
|
||||
vSnapped = true;
|
||||
if (hSnapped) {
|
||||
break;
|
||||
}
|
||||
if (qAbs (w_bottom - bottom) < snapdistance) {
|
||||
pos.setY (w_bottom - height ());
|
||||
pos.setY (w_bottom - ref->height () - attached[ref].y ());
|
||||
hSnapped = true;
|
||||
break;
|
||||
} else if (qAbs (w_top - top) < snapdistance) {
|
||||
pos.setY (w_top);
|
||||
pos.setY (w_top - attached[ref].y ());
|
||||
hSnapped = true;
|
||||
break;
|
||||
}
|
||||
} else if (!snappedV && (qAbs (left - w_right) < snapdistance)) {
|
||||
pos.setX (w_right);
|
||||
snappedV = true;
|
||||
if (snappedH) {
|
||||
} else if (!vSnapped && (qAbs (left - w_right) < snapdistance)) {
|
||||
pos.setX (w_right - attached[ref].x ());
|
||||
vSnapped = true;
|
||||
if (hSnapped) {
|
||||
break;
|
||||
}
|
||||
if (qAbs (w_bottom - bottom) < snapdistance) {
|
||||
pos.setY (w_bottom - height ());
|
||||
pos.setY (w_bottom - ref->height () - attached[ref].y ());
|
||||
hSnapped = true;
|
||||
break;
|
||||
} else if (qAbs (w_top - top) < snapdistance) {
|
||||
pos.setY (w_top);
|
||||
pos.setY (w_top - attached[ref].y ());
|
||||
hSnapped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// test if this widget can snap to top or bottom of another widget
|
||||
// and if it can, test if the left or right edges also can
|
||||
if (!snappedH && (qAbs (top - w_bottom) < snapdistance)) {
|
||||
pos.setY (w_bottom);
|
||||
snappedH = true;
|
||||
if (snappedV) {
|
||||
if ((!hSnapped) && (qAbs (top - w_bottom) < snapdistance)) {
|
||||
pos.setY (w_bottom - attached[ref].y ());
|
||||
hSnapped = true;
|
||||
if (vSnapped) {
|
||||
break;
|
||||
}
|
||||
if (qAbs (w_left - left) < snapdistance) {
|
||||
pos.setX (w_left);
|
||||
pos.setX (w_left - attached[ref].x ());
|
||||
vSnapped = true;
|
||||
break;
|
||||
} else if (qAbs (w_right - right) < snapdistance) {
|
||||
pos.setX (w_right - width ());
|
||||
pos.setX (w_right - ref->width () - attached[ref].x ());
|
||||
vSnapped = true;
|
||||
break;
|
||||
}
|
||||
} else if (!snappedH && (qAbs (w_top - bottom) < snapdistance)) {
|
||||
pos.setY (w_top - height ());
|
||||
snappedH = true;
|
||||
if (snappedV) {
|
||||
} else if ((!hSnapped) && (qAbs (w_top - bottom) < snapdistance)) {
|
||||
pos.setY (w_top - ref->height () - attached[ref].y ());
|
||||
hSnapped = true;
|
||||
if (vSnapped) {
|
||||
break;
|
||||
}
|
||||
if (qAbs (w_left - left) < snapdistance) {
|
||||
pos.setX (w_left);
|
||||
pos.setX (w_left - attached[ref].x ());
|
||||
vSnapped = true;
|
||||
break;
|
||||
} else if (qAbs (w_right - right) < snapdistance) {
|
||||
pos.setX (w_right - width ());
|
||||
pos.setX (w_right - ref->width () - attached[ref].x ());
|
||||
vSnapped = true;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
} // end foreach (w, widgets)
|
||||
|
||||
if (hSnapped && vSnapped) {
|
||||
break;
|
||||
}
|
||||
} // end foreach (ref, attached)
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
/*
|
||||
if (!widgets.isEmpty ()) {
|
||||
QPoint ret = testSnapWindow (this, pos, widgets);
|
||||
// test is attached Windows can snap to a unattached window
|
||||
if (((ret.x () == -1) || (ret.y () == -1)) && (!attached.isEmpty ())) {
|
||||
QPoint tmp;
|
||||
foreach (w, attached.keys ()) {
|
||||
tmp = testSnapWindow (w, pos + attached[w], widgets);
|
||||
if ((ret.x () == -1) && (tmp.x () > -1)) {
|
||||
ret.setX (tmp.x () - attached[w].x ());
|
||||
}
|
||||
if ((ret.y () == -1) && (tmp.y () > -1)) {
|
||||
ret.setY (tmp.y () - attached[w]. y());
|
||||
}
|
||||
ret = mergePoint (ret, tmp);
|
||||
if ((ret.x () > -1) && (ret.y () > -1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Subwindows didn't provide snap target for x and y axis:
|
||||
ret = mergePoint (ret, pos);
|
||||
return ret;
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -18,11 +18,16 @@
|
|||
#define __BASEWINDOW_H__
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QPoint>
|
||||
#include <QMap>
|
||||
class QMouseEvent;
|
||||
class QPoint;
|
||||
|
||||
class MainWindow;
|
||||
|
||||
class BaseWindow;
|
||||
typedef QMap<BaseWindow *, QPoint> AttachedWindowMap;
|
||||
|
||||
class BaseWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -37,7 +42,7 @@ class BaseWindow : public QMainWindow {
|
|||
void mouseReleaseEvent (QMouseEvent *event);
|
||||
void mouseMoveEvent (QMouseEvent *event);
|
||||
|
||||
QPoint snapWindow (QPoint pos, QWidgetList ignore = QWidgetList());
|
||||
QPoint snapWindow (QPoint pos, AttachedWindowMap attached = AttachedWindowMap());
|
||||
QPoint m_diff;
|
||||
};
|
||||
|
||||
|
|
|
@ -132,12 +132,12 @@ void
|
|||
MainWindow::mouseMoveEvent (QMouseEvent *event)
|
||||
{
|
||||
if ((event->buttons () & Qt::LeftButton) && !m_diff.isNull ()) {
|
||||
QWidgetList ignore;
|
||||
QWidget *w;
|
||||
foreach (w, m_attachedWidgets.keys ()) {
|
||||
ignore.append (w);
|
||||
}
|
||||
move (snapWindow (event->globalPos() - m_diff, ignore));
|
||||
// QWidgetList attached;
|
||||
// QWidget *w;
|
||||
// foreach (w, m_attachedWidgets.keys ()) {
|
||||
// attached.append (w);
|
||||
// }
|
||||
move (snapWindow (event->globalPos() - m_diff, m_attachedWidgets));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,7 +169,7 @@ MainWindow::attachWidgets ()
|
|||
if (w == this) {
|
||||
continue;
|
||||
}
|
||||
if (w->inherits ("BaseWindow")) {
|
||||
if ((w->inherits ("BaseWindow")) && (w->isVisible ())) {
|
||||
widgets.append (qobject_cast<BaseWindow *> (w));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue