kde-workspace/kdm/kcm/positioner.cpp

223 lines
5.8 KiB
C++
Raw Normal View History

2014-11-13 19:30:51 +02:00
/*
Copyright (C) 2006 Oswald Buddenhagen <ossi@kde.org>
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 Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "positioner.h"
#include <klocale.h>
#include <kstandarddirs.h>
#include <QFrame>
#include <QLabel>
#include <QMouseEvent>
#include <QDesktopWidget>
#include <QApplication>
#define TOTAL_WIDTH 200
#define TOTAL_HEIGHT 186
#define ACTIVE_X 23
#define ACTIVE_Y 14
#define ACTIVE_WIDTH 151
#define ACTIVE_HEIGHT 115
#define MARGIN 10
#define SNAP 10
#define STEP 5
static void
fit(int &p)
{
if (p < SNAP)
p = 0;
else if (p > 100 - SNAP)
p = 100;
else if (p > 50 - SNAP / 2 && p < 50 + SNAP / 2)
p = 50;
}
static void
step(int &p, int d)
{
if (p < SNAP)
p = 0 + (d + 1) * SNAP / 2;
else if (p > 100 - SNAP)
p = 100 + (d - 1) * SNAP / 2;
else if (p > 50 - SNAP / 2 && p < 50 + SNAP / 2)
p = 50 + d * SNAP / 2;
else {
p += d * STEP;
fit(p);
}
}
Positioner::Positioner(QWidget *parent)
: ScreenPreviewWidget(parent)
, m_x(50)
, m_y(50)
{
QDesktopWidget *desktop = QApplication::desktop();
setRatio((qreal)desktop->width() / (qreal)desktop->height());
m_anchor = QPixmap(KStandardDirs::locate("data", "kcontrol/pics/anchor.png"));
setFocusPolicy(Qt::StrongFocus);
const int fw = MARGIN * 2;
setMinimumSize(TOTAL_WIDTH + fw, TOTAL_HEIGHT + fw);
setMaximumWidth(400);
QSizePolicy sp(QSizePolicy::Expanding, QSizePolicy::Expanding);
sp.setHeightForWidth(true);
setSizePolicy(sp);
m_frame = new QFrame(this);
m_screen = new QWidget(m_frame);
m_screen->setAutoFillBackground(true);
QPalette pal;
pal.setColor(QPalette::Background, QColor(255, 255, 255, 128));
m_screen->setPalette(pal);
m_dlg = new QFrame(m_screen);
m_dlg->setFrameStyle(QFrame::Panel | QFrame::Raised);
m_dlg->setAutoFillBackground(true);
QPalette pal2;
pal2.setBrush(QPalette::Background, pal2.brush(QPalette::Normal, QPalette::Background));
m_dlg->setPalette(pal2);
m_ptr = new QLabel(m_screen);
m_ptr->setPixmap(m_anchor);
QString wts(i18n(
"Drag the anchor to move the center of the dialog to the desired position. "
"Keyboard control is possible as well: Use the arrow keys or Home to center. "
"Note that the actual proportions of the dialog are probably different."));
m_frame->setWhatsThis(wts);
m_screen->setWhatsThis(wts);
m_ptr->setWhatsThis(wts);
}
void
Positioner::setPosition(int x, int y)
{
m_x = x;
m_y = y;
updateHandle();
}
int
Positioner::heightForWidth(int w) const
{
const int fw = MARGIN * 2;
return ((w - fw) * TOTAL_HEIGHT + (TOTAL_WIDTH / 2)) / TOTAL_WIDTH + fw;
}
void
Positioner::updateHandle()
{
int px = m_screen->size().width() * m_x / 100;
int py = m_screen->size().height() * m_y / 100;
m_ptr->setGeometry(px - m_anchor.width() / 2, py - m_anchor.height() / 2,
m_anchor.width(), m_anchor.height());
int sw = m_screen->width() * 2 / 5;
int sh = m_screen->height() * 2 / 5;
QRect grt(px - sw / 2, py - sh / 2, sw, sh);
int di;
if ((di = m_screen->size().width() - grt.right()) < 0)
grt.translate(di, 0);
if ((di = - grt.left()) > 0)
grt.translate(di, 0);
if ((di = m_screen->size().height() - grt.bottom()) < 0)
grt.translate(0, di);
if ((di = - grt.top()) > 0)
grt.translate(0, di);
m_dlg->setGeometry(grt);
}
void
Positioner::resizeEvent(QResizeEvent *event)
{
ScreenPreviewWidget::resizeEvent(event);
const int fw = MARGIN * 2;
QSize rs(TOTAL_WIDTH, TOTAL_HEIGHT);
rs.scale(size() - QSize(fw, fw), Qt::KeepAspectRatio);
m_frame->setGeometry(0, 0, rs.width() + fw, rs.height() + fw);
m_frame->resize(size());
m_screen->setGeometry(previewRect());
updateHandle();
}
void
Positioner::focusInEvent(QFocusEvent *)
{
m_frame->setFrameStyle(QFrame::Panel | QFrame::Sunken);
}
void
Positioner::focusOutEvent(QFocusEvent *)
{
m_frame->setFrameStyle(QFrame::NoFrame);
}
void
Positioner::mousePressEvent(QMouseEvent *event)
{
QPoint cp = event->pos() - m_screen->pos();
if (m_ptr->geometry().contains(cp))
m_delta = m_ptr->geometry().center() - cp;
else
m_delta.setX(-1);
}
void
Positioner::mouseMoveEvent(QMouseEvent *event)
{
if (m_delta.x() != -1) {
QPoint cp = event->pos() - m_screen->pos() + m_delta;
m_x = cp.x() * 100 / m_screen->size().width();
m_y = cp.y() * 100 / m_screen->size().height();
fit(m_x);
fit(m_y);
updateHandle();
emit positionChanged();
}
}
void
Positioner::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Home:
m_x = m_y = 50;
break;
case Qt::Key_Left:
step(m_x, -1);
break;
case Qt::Key_Right:
step(m_x, 1);
break;
case Qt::Key_Up:
step(m_y, -1);
break;
case Qt::Key_Down:
step(m_y, 1);
break;
default:
event->ignore();
return;
}
updateHandle();
emit positionChanged();
event->accept();
}
#include "positioner.moc"