new panel containment positioning strategy: stacking horiz and non-horiz panels together vertically and horizontally, respectively
svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=784842
This commit is contained in:
parent
f118a132f1
commit
e702ebca9a
129
containment.cpp
129
containment.cpp
@ -51,6 +51,7 @@ namespace Plasma
|
||||
{
|
||||
|
||||
static const int INTER_CONTAINMENT_MARGIN = 6;
|
||||
static const int VERTICAL_STACKING_OFFSET = 10000;
|
||||
|
||||
class Containment::Private
|
||||
{
|
||||
@ -223,6 +224,11 @@ void Containment::containmentConstraintsUpdated(Plasma::Constraints constraints)
|
||||
d->toolbox->setPos(geometry().width() - d->toolbox->boundingRect().width(), 0);
|
||||
d->toolbox->enableTool("addwidgets", !isImmutable());
|
||||
}
|
||||
|
||||
if (constraints & Plasma::SizeConstraint &&
|
||||
containmentType() == PanelContainment) {
|
||||
positionPanel();
|
||||
}
|
||||
}
|
||||
|
||||
Containment::Type Containment::containmentType() const
|
||||
@ -395,12 +401,13 @@ void Containment::setFormFactor(FormFactor formFactor)
|
||||
}
|
||||
|
||||
//kDebug() << "switching FF to " << formFactor;
|
||||
FormFactor was = d->formFactor;
|
||||
d->formFactor = formFactor;
|
||||
Layout *lay = 0;
|
||||
//note: setting a new layout autodeletes the old one
|
||||
//and creating a layout calls setLayout on the parent
|
||||
|
||||
switch (d->formFactor) {
|
||||
switch (formFactor) {
|
||||
case Planar:
|
||||
case MediaCenter:
|
||||
lay = new FreeLayout(this);
|
||||
@ -421,6 +428,12 @@ void Containment::setFormFactor(FormFactor formFactor)
|
||||
break;
|
||||
}
|
||||
|
||||
if (containmentType() == PanelContainment && was != formFactor) {
|
||||
// we are a panel and we have chaged our orientation
|
||||
positionPanel(true);
|
||||
}
|
||||
|
||||
|
||||
if (lay) {
|
||||
foreach (Applet* applet, d->applets) {
|
||||
lay->addItem(applet);
|
||||
@ -651,7 +664,8 @@ int Containment::indexAt(const QPointF &pos) const
|
||||
void Containment::prepareApplet(Applet *applet, bool delayInit)
|
||||
{
|
||||
if (delayInit) {
|
||||
if (containmentType() == DesktopContainment) {
|
||||
if (containmentType() == DesktopContainment ||
|
||||
containmentType() == CustomContainment) {
|
||||
applet->installSceneEventFilter(this);
|
||||
}
|
||||
} else {
|
||||
@ -745,7 +759,8 @@ void Containment::appletAnimationComplete(QGraphicsItem *item, Plasma::Phase::An
|
||||
parent = parent->parentItem();
|
||||
}
|
||||
} else if (anim == Phase::Appear) {
|
||||
if (containmentType() == DesktopContainment &&
|
||||
if ((containmentType() == DesktopContainment ||
|
||||
containmentType() == CustomContainment) &&
|
||||
item->parentItem() == this &&
|
||||
qgraphicsitem_cast<Applet*>(item)) {
|
||||
item->installSceneEventFilter(this);
|
||||
@ -761,8 +776,7 @@ Applet::List Containment::applets() const
|
||||
void Containment::setScreen(int screen)
|
||||
{
|
||||
// screen of -1 means no associated screen.
|
||||
// sanity check to make sure someone else doesn't have this screen already!
|
||||
if (containmentType() == DesktopContainment) {
|
||||
if (containmentType() == DesktopContainment || containmentType() == CustomContainment) {
|
||||
// we want to listen to changes in work area if our screen changes
|
||||
if (d->screen < 0 && screen > -1) {
|
||||
connect(KWindowSystem::self(), SIGNAL(workAreaChanged()), this, SLOT(repositionToolbox()));
|
||||
@ -771,6 +785,7 @@ void Containment::setScreen(int screen)
|
||||
}
|
||||
|
||||
if (screen > -1 && corona()) {
|
||||
// sanity check to make sure someone else doesn't have this screen already!
|
||||
Containment* currently = corona()->containmentForScreen(screen);
|
||||
if (currently && currently != this) {
|
||||
//kDebug() << "currently is on screen" << currently->screen() << "and is" << currently->name() << (QObject*)currently << (QObject*)this;
|
||||
@ -790,7 +805,8 @@ void Containment::setScreen(int screen)
|
||||
if (screen < numScreens && screen > -1) {
|
||||
QRect r = desktop->screenGeometry(screen);
|
||||
|
||||
if (containmentType() == DesktopContainment) {
|
||||
if (containmentType() == DesktopContainment ||
|
||||
containmentType() == CustomContainment) {
|
||||
// we need to find how many screens are to our top and left
|
||||
// to calculate the proper offsets for the margins.
|
||||
int x = r.x();
|
||||
@ -815,12 +831,6 @@ void Containment::setScreen(int screen)
|
||||
// given screen! we should change the pos() on new containment setup.
|
||||
setGeometry(r);
|
||||
//kDebug() << "setting geometry to" << desktop->screenGeometry(screen) << r << geometry();
|
||||
} else if (containmentType() == PanelContainment) {
|
||||
//kDebug() << "we are a panel on" << r << ", let's move ourselves to a negative coordinate system" << -(r.y() * 2) - r.height() - INTER_CONTAINMENT_MARGIN;
|
||||
// panels are moved into negative coords; we double the x() so that each screen get's
|
||||
// it's own area for panels
|
||||
int vertOffset = (r.y() * 2) + r.height() + INTER_CONTAINMENT_MARGIN;
|
||||
translate(0, -vertOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@ -828,6 +838,79 @@ void Containment::setScreen(int screen)
|
||||
updateConstraints(Plasma::ScreenConstraint);
|
||||
}
|
||||
|
||||
void Containment::positionPanel(bool force)
|
||||
{
|
||||
if (!scene()) {
|
||||
kDebug() << "no scene yet";
|
||||
return;
|
||||
}
|
||||
|
||||
// we position panels in negative coordinates, and stack all horizontal
|
||||
// and all vertical panels with each other.
|
||||
|
||||
const QPointF p = pos();
|
||||
|
||||
if (!force &&
|
||||
p.y() + size().height() < -INTER_CONTAINMENT_MARGIN &&
|
||||
scene()->collidingItems(this).isEmpty()) {
|
||||
// already positioned and not running into any other panels
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO: research how non-Horizontal, non-Vertical (e.g. Planar) panels behave here
|
||||
bool horiz = formFactor() == Plasma::Horizontal;
|
||||
qreal bottom = horiz ? 0 : VERTICAL_STACKING_OFFSET;
|
||||
qreal lastHeight = 0;
|
||||
|
||||
// this should be ok for small numbers of panels, but we ever end
|
||||
// up managing hundreds of them, this simplistic alogrithm will
|
||||
// likely be too slow.
|
||||
foreach (const Containment* other, corona()->containments()) {
|
||||
if (other == this ||
|
||||
other->containmentType() != PanelContainment ||
|
||||
horiz != (other->formFactor() == Plasma::Horizontal)) {
|
||||
// only line up with panels of the same orientation
|
||||
continue;
|
||||
}
|
||||
|
||||
if (horiz) {
|
||||
qreal y = other->pos().y();
|
||||
if (y < bottom) {
|
||||
lastHeight = other->size().height();
|
||||
bottom = y;
|
||||
}
|
||||
} else {
|
||||
qreal width = other->size().width();
|
||||
qreal x = other->pos().x() + width;
|
||||
if (x > bottom) {
|
||||
lastHeight = width;
|
||||
bottom = x + lastHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kDebug() << "positioning" << (horiz ? "" : "non-") << "horizontal panel; forced?" << force;
|
||||
// give a space equal to the height again of the last item so there is
|
||||
// room to grow.
|
||||
QPointF newPos;
|
||||
if (horiz) {
|
||||
bottom -= lastHeight + INTER_CONTAINMENT_MARGIN;
|
||||
//TODO: fix x position for non-flush-left panels
|
||||
kDebug() << "moved to" << QPointF(0, bottom - size().height());
|
||||
newPos = QPointF(0, bottom - size().height());
|
||||
} else {
|
||||
bottom += lastHeight + INTER_CONTAINMENT_MARGIN;
|
||||
//TODO: fix y position for non-flush-top panels
|
||||
kDebug() << "moved to" << QPointF(bottom + size().width(), -INTER_CONTAINMENT_MARGIN - size().height());
|
||||
newPos = QPointF(bottom + size().width(), -INTER_CONTAINMENT_MARGIN - size().height());
|
||||
}
|
||||
|
||||
if (p != newPos) {
|
||||
setPos(newPos);
|
||||
emit geometryChanged();
|
||||
}
|
||||
}
|
||||
|
||||
int Containment::screen() const
|
||||
{
|
||||
return d->screen;
|
||||
@ -881,6 +964,8 @@ void Containment::dropEvent(QGraphicsSceneDragDropEvent *event)
|
||||
addApplet(plasmoidName, QVariantList(), 0, geom);
|
||||
event->acceptProposedAction();
|
||||
} else if (KUrl::List::canDecode(event->mimeData())) {
|
||||
//TODO: collect the mimetypes of available script engines and offer
|
||||
// to create widgets out of the matching URLs, if any
|
||||
KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());
|
||||
foreach (const KUrl& url, urls) {
|
||||
KMimeType::Ptr mime = KMimeType::findByUrl(url);
|
||||
@ -975,6 +1060,18 @@ void Containment::handleDisappeared(AppletHandle *handle)
|
||||
handle->deleteLater();
|
||||
}
|
||||
|
||||
QVariant Containment::itemChange(GraphicsItemChange change, const QVariant &value)
|
||||
{
|
||||
Q_UNUSED(value)
|
||||
|
||||
if (change == QGraphicsItem::ItemPositionHasChanged &&
|
||||
containmentType() == PanelContainment) {
|
||||
positionPanel();
|
||||
}
|
||||
|
||||
return Applet::itemChange(change, value);
|
||||
}
|
||||
|
||||
void Containment::emitLaunchActivated()
|
||||
{
|
||||
kDebug();
|
||||
@ -1011,12 +1108,16 @@ bool Containment::isToolboxToolEnabled(const QString &toolname) const
|
||||
|
||||
void Containment::showToolbox()
|
||||
{
|
||||
d->createToolbox()->showToolbox();
|
||||
if (d->toolbox) {
|
||||
d->toolbox->showToolbox();
|
||||
}
|
||||
}
|
||||
|
||||
void Containment::hideToolbox()
|
||||
{
|
||||
d->createToolbox()->hideToolbox();
|
||||
if (d->toolbox) {
|
||||
d->toolbox->hideToolbox();
|
||||
}
|
||||
}
|
||||
|
||||
void Containment::repositionToolbox()
|
||||
|
@ -348,6 +348,7 @@ class PLASMA_EXPORT Containment : public Applet
|
||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
||||
bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
|
||||
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
|
||||
|
||||
protected Q_SLOTS:
|
||||
/**
|
||||
@ -370,8 +371,7 @@ class PLASMA_EXPORT Containment : public Applet
|
||||
QRectF geometryForApplet(Applet *applet) const;
|
||||
bool regionIsEmpty(const QRectF ®ion, Applet *ignoredApplet=0) const;
|
||||
void prepareApplet(Applet *applet, bool delayInit);
|
||||
|
||||
Q_DISABLE_COPY(Containment)
|
||||
void positionPanel(bool force = false);
|
||||
|
||||
class Private;
|
||||
Private* const d;
|
||||
|
Loading…
x
Reference in New Issue
Block a user