add more spacing
[personal-kdebase.git] / workspace / kcontrol / kdm / positioner.cpp
blob3d15961920a3a56b1fd3dcc5df301d7a677056bf
1 /*
2 Copyright (C) 2006 Oswald Buddenhagen <ossi@kde.org>
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
20 #include "positioner.h"
22 #include <klocale.h>
23 #include <kstandarddirs.h>
25 #include <QFrame>
26 #include <QLabel>
27 #include <QMouseEvent>
28 #include <QPainter>
30 #define TOTAL_WIDTH 200
31 #define TOTAL_HEIGHT 186
32 #define ACTIVE_X 23
33 #define ACTIVE_Y 14
34 #define ACTIVE_WIDTH 151
35 #define ACTIVE_HEIGHT 115
36 #define MARGIN 10
38 #define SNAP 10
39 #define STEP 5
41 static void
42 fit( int &p )
44 if (p < SNAP)
45 p = 0;
46 else if (p > 100 - SNAP)
47 p = 100;
48 else if (p > 50 - SNAP / 2 && p < 50 + SNAP / 2)
49 p = 50;
52 static void
53 step( int &p, int d )
55 if (p < SNAP)
56 p = 0 + (d + 1) * SNAP / 2;
57 else if (p > 100 - SNAP)
58 p = 100 + (d - 1) * SNAP / 2;
59 else if (p > 50 - SNAP / 2 && p < 50 + SNAP / 2)
60 p = 50 + d * SNAP / 2;
61 else {
62 p += d * STEP;
63 fit( p );
67 Positioner::Positioner( QWidget *parent )
68 : QWidget( parent )
69 , m_readOnly( false )
70 , m_x( 50 )
71 , m_y( 50 )
73 m_monitor = QImage( KStandardDirs::locate( "data", "kcontrol/pics/monitor.png" ) );
74 m_anchor = QPixmap( KStandardDirs::locate( "data", "kcontrol/pics/anchor.png" ) );
75 setFocusPolicy( Qt::StrongFocus );
76 const int fw = MARGIN * 2;
77 setMinimumSize( TOTAL_WIDTH + fw, TOTAL_HEIGHT + fw );
78 setMaximumWidth( 400 );
79 QSizePolicy sp( QSizePolicy::Expanding, QSizePolicy::Expanding );
80 sp.setHeightForWidth( true );
81 setSizePolicy( sp );
82 m_frame = new QFrame( this );
83 m_screen = new QWidget( m_frame );
84 m_screen->setAutoFillBackground( true );
85 QPalette pal;
86 pal.setColor( QPalette::Background, QColor( 255, 255, 255, 128 ) );
87 m_screen->setPalette( pal );
88 m_dlg = new QFrame( m_screen );
89 m_dlg->setFrameStyle( QFrame::Panel | QFrame::Raised );
90 m_dlg->setAutoFillBackground( true );
91 QPalette pal2;
92 pal2.setBrush( QPalette::Background, pal2.brush( QPalette::Normal, QPalette::Background ) );
93 m_dlg->setPalette( pal2 );
94 m_ptr = new QLabel( m_screen );
95 m_ptr->setPixmap( m_anchor );
96 QString wts( i18n(
97 "Drag the anchor to move the center of the dialog to the desired position. "
98 "Keyboard control is possible as well: Use the arrow keys or Home to center. "
99 "Note that the actual proportions of the dialog are probably different.") );
100 m_frame->setWhatsThis( wts );
101 m_screen->setWhatsThis( wts );
102 m_ptr->setWhatsThis( wts );
105 void
106 Positioner::setPosition( int x, int y )
108 m_x = x;
109 m_y = y;
110 updateHandle();
114 Positioner::heightForWidth( int w ) const
116 const int fw = MARGIN * 2;
117 return ((w - fw) * TOTAL_HEIGHT + (TOTAL_WIDTH / 2)) / TOTAL_WIDTH + fw;
120 void
121 Positioner::updateHandle()
123 int px = m_screen->size().width() * m_x / 100;
124 int py = m_screen->size().height() * m_y / 100;
125 m_ptr->setGeometry( px - m_anchor.width() / 2, py - m_anchor.height() / 2,
126 m_anchor.width(), m_anchor.height() );
127 int sw = m_screen->width() * 2 / 5;
128 int sh = m_screen->height() * 2 / 5;
129 QRect grt( px - sw / 2, py - sh / 2, sw, sh );
130 int di;
131 if ((di = m_screen->size().width() - grt.right()) < 0)
132 grt.translate( di, 0 );
133 if ((di = - grt.left()) > 0)
134 grt.translate( di, 0 );
135 if ((di = m_screen->size().height() - grt.bottom()) < 0)
136 grt.translate( 0, di );
137 if ((di = - grt.top()) > 0)
138 grt.translate( 0, di );
139 m_dlg->setGeometry( grt );
142 void
143 Positioner::resizeEvent( QResizeEvent * )
145 const int fw = MARGIN * 2;
146 QSize rs( TOTAL_WIDTH, TOTAL_HEIGHT );
147 rs.scale( size() - QSize( fw, fw ), Qt::KeepAspectRatio );
148 m_scaledMonitor = QPixmap::fromImage(
149 m_monitor.scaled( rs, Qt::KeepAspectRatio, Qt::SmoothTransformation ) );
150 m_frame->setGeometry( 0, 0, rs.width() + fw, rs.height() + fw );
151 m_screen->setGeometry(
152 MARGIN + ACTIVE_X * m_scaledMonitor.width() / TOTAL_WIDTH,
153 MARGIN + ACTIVE_Y * m_scaledMonitor.height() / TOTAL_HEIGHT,
154 ACTIVE_WIDTH * m_scaledMonitor.width() / TOTAL_WIDTH,
155 ACTIVE_HEIGHT * m_scaledMonitor.height() / TOTAL_HEIGHT );
156 updateHandle();
159 void
160 Positioner::focusInEvent( QFocusEvent * )
162 m_frame->setFrameStyle( QFrame::Panel | QFrame::Sunken );
165 void
166 Positioner::focusOutEvent( QFocusEvent * )
168 m_frame->setFrameStyle( QFrame::NoFrame );
171 void
172 Positioner::paintEvent( QPaintEvent * )
174 QPainter p( this );
175 p.drawPixmap( MARGIN, MARGIN, m_scaledMonitor );
178 void
179 Positioner::mousePressEvent( QMouseEvent *event )
181 QPoint cp = event->pos() - m_screen->pos();
182 if (!m_readOnly && m_ptr->geometry().contains( cp ))
183 m_delta = m_ptr->geometry().center() - cp;
184 else
185 m_delta.setX( -1 );
188 void
189 Positioner::mouseMoveEvent( QMouseEvent *event )
191 if (m_delta.x() != -1) {
192 QPoint cp = event->pos() - m_screen->pos() + m_delta;
193 m_x = cp.x() * 100 / m_screen->size().width();
194 m_y = cp.y() * 100 / m_screen->size().height();
195 fit( m_x );
196 fit( m_y );
197 updateHandle();
198 emit positionChanged();
202 void
203 Positioner::keyPressEvent( QKeyEvent *event )
205 switch (event->key()) {
206 case Qt::Key_Home:
207 m_x = m_y = 50;
208 break;
209 case Qt::Key_Left:
210 step( m_x, -1 );
211 break;
212 case Qt::Key_Right:
213 step( m_x, 1 );
214 break;
215 case Qt::Key_Up:
216 step( m_y, -1 );
217 break;
218 case Qt::Key_Down:
219 step( m_y, 1 );
220 break;
221 default:
222 event->ignore();
223 return;
225 updateHandle();
226 emit positionChanged();
227 event->accept();
230 #include "positioner.moc"