Fix some error
[kdeartwork.git] / kscreensaver / xsavers / swarm.cpp
blob343c4d4273d054fe371d5bab0923da799c33e274
1 /*-
2 * swarm.c - swarm of bees for xlock, the X Window System lockscreen.
4 * Copyright (c) 1991 by Patrick J. Naughton.
6 * Revision History:
7 * 31-Aug-90: Adapted from xswarm by Jeff Butterworth. (butterwo@ncsc.org)
8 */
10 /* Ported to kscreensaver:
11 July 1997, Emanuel Pirker <epirker@edu.uni-klu.ac.at>
12 Contact me in case of problems, not the original author!
13 Last revised: 10-Jul-97
15 // layout management added 1998/04/19 by Mario Weilguni <mweilguni@kde.org>
17 #define MAXSPEED 100
18 #define MINSPEED 0
19 #define DEFSPEED 50
20 #define MAXBATCH 200
21 #define MINBATCH 0
22 #define DEFBATCH 20
24 #include <qslider.h>
25 //Added by qt3to4:
26 #include <QVBoxLayout>
27 #include <QHBoxLayout>
28 #include <kglobal.h>
29 #include <kconfig.h>
30 #include <krandomsequence.h>
31 #include "xlock.h"
33 #undef index
35 #define TIMES 4 /* number of time positions recorded */
36 #define BEEACC 2 /* acceleration of bees */
37 #define WASPACC 5 /* maximum acceleration of wasp */
38 #define BEEVEL 12 /* maximum bee velocity */
39 #define WASPVEL 10 /* maximum wasp velocity */
41 /* Macros */
42 #define X(t,b) (sp->x[(t)*sp->beecount+(b)])
43 #define Y(t,b) (sp->y[(t)*sp->beecount+(b)])
44 #define balance_rand(v) (rnd.getLong(v)-((v)/2)) /* random number around 0 */
46 //ModeSpecOpt swarm_opts = {0, NULL, NULL, NULL};
48 typedef struct {
49 int pix;
50 int width;
51 int height;
52 int border; /* wasp won't go closer than this to the edge */
53 int beecount; /* number of bees */
54 XSegment segs[MAXBATCH]; /* bee lines */
55 XSegment old_segs[MAXBATCH]; /* old bee lines */
56 short x[MAXBATCH*TIMES];
57 short y[MAXBATCH*TIMES]; /* bee positions x[time][bee#] */
58 short xv[MAXBATCH];
59 short yv[MAXBATCH]; /* bee velocities xv[bee#] */
60 short wx[3];
61 short wy[3];
62 short wxv;
63 short wyv;
64 } swarmstruct;
66 static swarmstruct swarms[MAXSCREENS];
68 void
69 initswarm(Window win, KRandomSequence &rnd)
71 swarmstruct *sp = &swarms[screen];
72 int b;
73 XWindowAttributes xwa;
75 sp->beecount = batchcount;
76 (void) XGetWindowAttributes(dsp, win, &xwa);
77 sp->width = xwa.width;
78 sp->height = xwa.height;
80 sp->border = (sp->width + sp->height) / 50;
82 /* Clear the background. */
83 XSetForeground(dsp, Scr[screen].gc, BlackPixel(dsp, screen));
84 XFillRectangle(dsp, win, Scr[screen].gc, 0, 0, sp->width, sp->height);
86 /* Now static data structures. epirker */
87 //if (!sp->segs) {
88 //sp->segs = (XSegment *) malloc(sizeof (XSegment) * sp->beecount);
89 //sp->old_segs = (XSegment *) malloc(sizeof (XSegment) * sp->beecount);
90 //sp->x = (short *) malloc(sizeof (short) * sp->beecount * TIMES);
91 //sp->y = (short *) malloc(sizeof (short) * sp->beecount * TIMES);
92 //sp->xv = (short *) malloc(sizeof (short) * sp->beecount);
93 //sp->yv = (short *) malloc(sizeof (short) * sp->beecount);
94 //}
95 /* Initialize point positions, velocities, etc. */
97 /* wasp */
98 sp->wx[0] = sp->border + rnd.getLong(sp->width - 2 * sp->border);
99 sp->wy[0] = sp->border + rnd.getLong(sp->height - 2 * sp->border);
100 sp->wx[1] = sp->wx[0];
101 sp->wy[1] = sp->wy[0];
102 sp->wxv = 0;
103 sp->wyv = 0;
105 /* bees */
106 for (b = 0; b < sp->beecount; b++) {
107 X(0, b) = rnd.getLong(sp->width);
108 X(1, b) = X(0, b);
109 Y(0, b) = rnd.getLong(sp->height);
110 Y(1, b) = Y(0, b);
111 sp->xv[b] = balance_rand(7);
112 sp->yv[b] = balance_rand(7);
118 void
119 drawswarm(Window win, KRandomSequence &rnd)
121 swarmstruct *sp = &swarms[screen];
122 int b;
124 /* <=- Wasp -=> */
125 /* Age the arrays. */
126 sp->wx[2] = sp->wx[1];
127 sp->wx[1] = sp->wx[0];
128 sp->wy[2] = sp->wy[1];
129 sp->wy[1] = sp->wy[0];
130 /* Accelerate */
131 sp->wxv += balance_rand(WASPACC);
132 sp->wyv += balance_rand(WASPACC);
134 /* Speed Limit Checks */
135 if (sp->wxv > WASPVEL)
136 sp->wxv = WASPVEL;
137 if (sp->wxv < -WASPVEL)
138 sp->wxv = -WASPVEL;
139 if (sp->wyv > WASPVEL)
140 sp->wyv = WASPVEL;
141 if (sp->wyv < -WASPVEL)
142 sp->wyv = -WASPVEL;
144 /* Move */
145 sp->wx[0] = sp->wx[1] + sp->wxv;
146 sp->wy[0] = sp->wy[1] + sp->wyv;
148 /* Bounce Checks */
149 if ((sp->wx[0] < sp->border) || (sp->wx[0] > sp->width - sp->border - 1)) {
150 sp->wxv = -sp->wxv;
151 sp->wx[0] += sp->wxv;
153 if ((sp->wy[0] < sp->border) || (sp->wy[0] > sp->height - sp->border - 1)) {
154 sp->wyv = -sp->wyv;
155 sp->wy[0] += sp->wyv;
157 /* Don't let things settle down. */
158 sp->xv[rnd.getLong(sp->beecount)] += balance_rand(3);
159 sp->yv[rnd.getLong(sp->beecount)] += balance_rand(3);
161 /* <=- Bees -=> */
162 for (b = 0; b < sp->beecount; b++) {
163 int distance, dx, dy;
165 /* Age the arrays. */
166 X(2, b) = X(1, b);
167 X(1, b) = X(0, b);
168 Y(2, b) = Y(1, b);
169 Y(1, b) = Y(0, b);
171 /* Accelerate */
172 dx = sp->wx[1] - X(1, b);
173 dy = sp->wy[1] - Y(1, b);
174 distance = abs(dx) + abs(dy); /* approximation */
175 if (distance == 0)
176 distance = 1;
177 sp->xv[b] += (dx * BEEACC) / distance;
178 sp->yv[b] += (dy * BEEACC) / distance;
180 /* Speed Limit Checks */
181 if (sp->xv[b] > BEEVEL)
182 sp->xv[b] = BEEVEL;
183 if (sp->xv[b] < -BEEVEL)
184 sp->xv[b] = -BEEVEL;
185 if (sp->yv[b] > BEEVEL)
186 sp->yv[b] = BEEVEL;
187 if (sp->yv[b] < -BEEVEL)
188 sp->yv[b] = -BEEVEL;
190 /* Move */
191 X(0, b) = X(1, b) + sp->xv[b];
192 Y(0, b) = Y(1, b) + sp->yv[b];
194 /* Fill the segment lists. */
195 sp->segs[b].x1 = X(0, b);
196 sp->segs[b].y1 = Y(0, b);
197 sp->segs[b].x2 = X(1, b);
198 sp->segs[b].y2 = Y(1, b);
199 sp->old_segs[b].x1 = X(1, b);
200 sp->old_segs[b].y1 = Y(1, b);
201 sp->old_segs[b].x2 = X(2, b);
202 sp->old_segs[b].y2 = Y(2, b);
205 XSetForeground(dsp, Scr[screen].gc, BlackPixel(dsp, screen));
206 XDrawLine(dsp, win, Scr[screen].gc,
207 sp->wx[1], sp->wy[1], sp->wx[2], sp->wy[2]);
208 XDrawSegments(dsp, win, Scr[screen].gc, sp->old_segs, sp->beecount);
210 XSetForeground(dsp, Scr[screen].gc, WhitePixel(dsp, screen));
211 XDrawLine(dsp, win, Scr[screen].gc,
212 sp->wx[0], sp->wy[0], sp->wx[1], sp->wy[1]);
213 if (!mono && Scr[screen].npixels > 2) {
214 XSetForeground(dsp, Scr[screen].gc, Scr[screen].pixels[sp->pix]);
215 if (++sp->pix >= Scr[screen].npixels)
216 sp->pix = 0;
218 XDrawSegments(dsp, win, Scr[screen].gc, sp->segs, sp->beecount);
221 //-----------------------------------------------------------------------------
223 #include <qcheckbox.h>
224 #include <qlabel.h>
225 #include <qcolor.h>
226 #include <qlayout.h>
227 #include <QX11Info>
228 #include <klocale.h>
229 #include <kmessagebox.h>
231 #include "swarm.h"
232 #include "swarm.moc"
233 #include "helpers.h"
235 #undef Below
237 static kSwarmSaver *saver = NULL;
239 void startScreenSaver( Drawable d )
241 if ( saver )
242 return;
243 saver = new kSwarmSaver( d );
246 void stopScreenSaver()
248 if ( saver )
249 delete saver;
250 saver = NULL;
253 int setupScreenSaver()
255 kSwarmSetup dlg;
257 return dlg.exec();
260 //-----------------------------------------------------------------------------
262 kSwarmSaver::kSwarmSaver( Drawable drawable ) : kScreenSaver( drawable )
264 readSettings();
266 // Clear to background colour when exposed
267 XSetWindowBackground(QX11Info::display(), mDrawable,
268 BlackPixel(QX11Info::display(), QX11Info::appScreen()));
270 batchcount = maxLevels;
272 initXLock( mGc );
273 initswarm( mDrawable, rnd );
275 timer.start( speed );
276 connect( &timer, SIGNAL( timeout() ), SLOT( slotTimeout() ) );
279 kSwarmSaver::~kSwarmSaver()
281 timer.stop();
284 void kSwarmSaver::setSpeed( int spd )
286 timer.stop();
287 speed = MAXSPEED - spd;
288 timer.start( speed );
291 void kSwarmSaver::setLevels( int l )
293 batchcount = maxLevels = l;
294 initswarm( mDrawable, rnd );
297 void kSwarmSaver::readSettings()
299 KConfig *config = klock_config();
300 config->setGroup( "Settings" );
302 speed = MAXSPEED - config->readNumEntry( "Speed", MAXSPEED - DEFSPEED );
303 maxLevels = config->readNumEntry( "MaxLevels", DEFBATCH );
305 delete config;
308 void kSwarmSaver::slotTimeout()
310 drawswarm( mDrawable, rnd );
313 //-----------------------------------------------------------------------------
315 kSwarmSetup::kSwarmSetup( QWidget *parent, const char *name )
316 : KDialogBase( parent, name, true, i18n( "Setup Swarm Screen Saver" ),
317 Ok|Cancel|Help, Ok, true )
319 readSettings();
321 setButtonText( Help, i18n( "A&bout" ) );
322 QWidget *main = makeMainWidget();
324 QHBoxLayout *top = new QHBoxLayout( main/*, 0, spacingHint()*/ );
325 QVBoxLayout *left = new QVBoxLayout(0L);/*, spacingHint()*/
326 left->addLayout(top);
328 QLabel *label = new QLabel( i18n("Speed:"), main );
329 min_size(label);
330 left->addWidget(label);
332 QSlider *slider = new QSlider(Qt::Horizontal,main);
333 slider->setMaximum(MAXSPEED);
334 slider->setMinimum(MINSPEED);
335 slider->setValue(speed);
336 slider->setMinimumSize( 120, 20 );
337 slider->setTickPosition(QSlider::TicksBelow);
338 slider->setTickInterval(10);
339 connect( slider, SIGNAL( valueChanged( int ) ),
340 SLOT( slotSpeed( int ) ) );
341 left->addWidget(slider);
343 label = new QLabel( i18n("Number of bees:"), main );
344 min_size(label);
345 left->addWidget(label);
347 slider = new QSlider(Qt::Horizontal,main);
348 slider->setMaximum(MAXBATCH);
349 slider->setMinimum(MINBATCH);
350 slider->setValue(20);
352 slider->setMinimumSize( 120, 20 );
353 slider->setTickPosition(QSlider::TicksBelow);
354 slider->setTickInterval(20);
355 connect( slider, SIGNAL( valueChanged( int ) ),
356 SLOT( slotLevels( int ) ) );
357 left->addWidget(slider);
358 left->addStretch();
360 preview = new QWidget( main );
361 preview->setFixedSize( 220, 170 );
362 QPalette palette = preview->palette();
363 palette.setColor(preview->backgroundRole(), Qt::black);
364 preview->setPalette(palette);
366 preview->show(); // otherwise saver does not get correct size
367 saver = new kSwarmSaver( preview->winId() );
368 top->addWidget(preview);
370 top->addStretch();
373 void kSwarmSetup::readSettings()
375 KConfig *config = klock_config();
376 config->setGroup( "Settings" );
378 speed = config->readNumEntry( "Speed", speed );
380 if ( speed > MAXSPEED )
381 speed = MAXSPEED;
382 else if ( speed < MINSPEED )
383 speed = MINSPEED;
385 maxLevels = config->readNumEntry( "MaxLevels", DEFBATCH );
386 delete config;
389 void kSwarmSetup::slotSpeed( int num )
391 speed = num;
393 if ( saver )
394 saver->setSpeed( speed );
397 void kSwarmSetup::slotLevels( int num )
399 maxLevels = num;
401 if ( saver )
402 saver->setLevels( maxLevels );
405 void kSwarmSetup::slotOk()
407 KConfig *config = klock_config();
408 config->setGroup( "Settings" );
410 QString sspeed;
411 sspeed.setNum( speed );
412 config->writeEntry( "Speed", sspeed );
414 QString slevels;
415 slevels.setNum( maxLevels );
416 config->writeEntry( "MaxLevels", slevels );
418 config->sync();
419 delete config;
420 accept();
423 void kSwarmSetup::slotHelp()
425 KMessageBox::information(this,
426 i18n("Swarm\n\nCopyright (c) 1991 by Patrick J. Naughton\n\nPorted to kscreensaver by Emanuel Pirker."),
427 i18n("About Swarm"));