SVN_SILENT made messages (.desktop file)
[kdeartwork.git] / kscreensaver / xsavers / swarm.cpp
blobc133f9a94f514a44f7bc9816e29d073a60ffda9e
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
23 #include <qslider.h>
24 //Added by qt3to4:
25 #include <QVBoxLayout>
26 #include <QHBoxLayout>
27 #include <kglobal.h>
28 #include <kconfig.h>
29 #include <krandomsequence.h>
30 #include "xlock.h"
32 #undef index
34 #define TIMES 4 /* number of time positions recorded */
35 #define BEEACC 2 /* acceleration of bees */
36 #define WASPACC 5 /* maximum acceleration of wasp */
37 #define BEEVEL 12 /* maximum bee velocity */
38 #define WASPVEL 10 /* maximum wasp velocity */
40 /* Macros */
41 #define X(t,b) (sp->x[(t)*sp->beecount+(b)])
42 #define Y(t,b) (sp->y[(t)*sp->beecount+(b)])
43 #define balance_rand(v) (rnd.getLong(v)-((v)/2)) /* random number around 0 */
45 //ModeSpecOpt swarm_opts = {0, NULL, NULL, NULL};
47 typedef struct {
48 int pix;
49 int width;
50 int height;
51 int border; /* wasp won't go closer than this to the edge */
52 int beecount; /* number of bees */
53 XSegment segs[MAXBATCH]; /* bee lines */
54 XSegment old_segs[MAXBATCH]; /* old bee lines */
55 short x[MAXBATCH*TIMES];
56 short y[MAXBATCH*TIMES]; /* bee positions x[time][bee#] */
57 short xv[MAXBATCH];
58 short yv[MAXBATCH]; /* bee velocities xv[bee#] */
59 short wx[3];
60 short wy[3];
61 short wxv;
62 short wyv;
63 } swarmstruct;
65 static swarmstruct swarms[MAXSCREENS];
67 void
68 initswarm(Window win, KRandomSequence &rnd)
70 swarmstruct *sp = &swarms[screen];
71 int b;
72 XWindowAttributes xwa;
74 sp->beecount = batchcount;
75 (void) XGetWindowAttributes(dsp, win, &xwa);
76 sp->width = xwa.width;
77 sp->height = xwa.height;
79 sp->border = (sp->width + sp->height) / 50;
81 /* Clear the background. */
82 XSetForeground(dsp, Scr[screen].gc, BlackPixel(dsp, screen));
83 XFillRectangle(dsp, win, Scr[screen].gc, 0, 0, sp->width, sp->height);
85 /* Now static data structures. epirker */
86 //if (!sp->segs) {
87 //sp->segs = (XSegment *) malloc(sizeof (XSegment) * sp->beecount);
88 //sp->old_segs = (XSegment *) malloc(sizeof (XSegment) * sp->beecount);
89 //sp->x = (short *) malloc(sizeof (short) * sp->beecount * TIMES);
90 //sp->y = (short *) malloc(sizeof (short) * sp->beecount * TIMES);
91 //sp->xv = (short *) malloc(sizeof (short) * sp->beecount);
92 //sp->yv = (short *) malloc(sizeof (short) * sp->beecount);
93 //}
94 /* Initialize point positions, velocities, etc. */
96 /* wasp */
97 sp->wx[0] = sp->border + rnd.getLong(sp->width - 2 * sp->border);
98 sp->wy[0] = sp->border + rnd.getLong(sp->height - 2 * sp->border);
99 sp->wx[1] = sp->wx[0];
100 sp->wy[1] = sp->wy[0];
101 sp->wxv = 0;
102 sp->wyv = 0;
104 /* bees */
105 for (b = 0; b < sp->beecount; b++) {
106 X(0, b) = rnd.getLong(sp->width);
107 X(1, b) = X(0, b);
108 Y(0, b) = rnd.getLong(sp->height);
109 Y(1, b) = Y(0, b);
110 sp->xv[b] = balance_rand(7);
111 sp->yv[b] = balance_rand(7);
117 void
118 drawswarm(Window win, KRandomSequence &rnd)
120 swarmstruct *sp = &swarms[screen];
121 int b;
123 /* <=- Wasp -=> */
124 /* Age the arrays. */
125 sp->wx[2] = sp->wx[1];
126 sp->wx[1] = sp->wx[0];
127 sp->wy[2] = sp->wy[1];
128 sp->wy[1] = sp->wy[0];
129 /* Accelerate */
130 sp->wxv += balance_rand(WASPACC);
131 sp->wyv += balance_rand(WASPACC);
133 /* Speed Limit Checks */
134 if (sp->wxv > WASPVEL)
135 sp->wxv = WASPVEL;
136 if (sp->wxv < -WASPVEL)
137 sp->wxv = -WASPVEL;
138 if (sp->wyv > WASPVEL)
139 sp->wyv = WASPVEL;
140 if (sp->wyv < -WASPVEL)
141 sp->wyv = -WASPVEL;
143 /* Move */
144 sp->wx[0] = sp->wx[1] + sp->wxv;
145 sp->wy[0] = sp->wy[1] + sp->wyv;
147 /* Bounce Checks */
148 if ((sp->wx[0] < sp->border) || (sp->wx[0] > sp->width - sp->border - 1)) {
149 sp->wxv = -sp->wxv;
150 sp->wx[0] += sp->wxv;
152 if ((sp->wy[0] < sp->border) || (sp->wy[0] > sp->height - sp->border - 1)) {
153 sp->wyv = -sp->wyv;
154 sp->wy[0] += sp->wyv;
156 /* Don't let things settle down. */
157 sp->xv[rnd.getLong(sp->beecount)] += balance_rand(3);
158 sp->yv[rnd.getLong(sp->beecount)] += balance_rand(3);
160 /* <=- Bees -=> */
161 for (b = 0; b < sp->beecount; b++) {
162 int distance, dx, dy;
164 /* Age the arrays. */
165 X(2, b) = X(1, b);
166 X(1, b) = X(0, b);
167 Y(2, b) = Y(1, b);
168 Y(1, b) = Y(0, b);
170 /* Accelerate */
171 dx = sp->wx[1] - X(1, b);
172 dy = sp->wy[1] - Y(1, b);
173 distance = abs(dx) + abs(dy); /* approximation */
174 if (distance == 0)
175 distance = 1;
176 sp->xv[b] += (dx * BEEACC) / distance;
177 sp->yv[b] += (dy * BEEACC) / distance;
179 /* Speed Limit Checks */
180 if (sp->xv[b] > BEEVEL)
181 sp->xv[b] = BEEVEL;
182 if (sp->xv[b] < -BEEVEL)
183 sp->xv[b] = -BEEVEL;
184 if (sp->yv[b] > BEEVEL)
185 sp->yv[b] = BEEVEL;
186 if (sp->yv[b] < -BEEVEL)
187 sp->yv[b] = -BEEVEL;
189 /* Move */
190 X(0, b) = X(1, b) + sp->xv[b];
191 Y(0, b) = Y(1, b) + sp->yv[b];
193 /* Fill the segment lists. */
194 sp->segs[b].x1 = X(0, b);
195 sp->segs[b].y1 = Y(0, b);
196 sp->segs[b].x2 = X(1, b);
197 sp->segs[b].y2 = Y(1, b);
198 sp->old_segs[b].x1 = X(1, b);
199 sp->old_segs[b].y1 = Y(1, b);
200 sp->old_segs[b].x2 = X(2, b);
201 sp->old_segs[b].y2 = Y(2, b);
204 XSetForeground(dsp, Scr[screen].gc, BlackPixel(dsp, screen));
205 XDrawLine(dsp, win, Scr[screen].gc,
206 sp->wx[1], sp->wy[1], sp->wx[2], sp->wy[2]);
207 XDrawSegments(dsp, win, Scr[screen].gc, sp->old_segs, sp->beecount);
209 XSetForeground(dsp, Scr[screen].gc, WhitePixel(dsp, screen));
210 XDrawLine(dsp, win, Scr[screen].gc,
211 sp->wx[0], sp->wy[0], sp->wx[1], sp->wy[1]);
212 if (!mono && Scr[screen].npixels > 2) {
213 XSetForeground(dsp, Scr[screen].gc, Scr[screen].pixels[sp->pix]);
214 if (++sp->pix >= Scr[screen].npixels)
215 sp->pix = 0;
217 XDrawSegments(dsp, win, Scr[screen].gc, sp->segs, sp->beecount);
220 //-----------------------------------------------------------------------------
222 #include <qcheckbox.h>
223 #include <qlabel.h>
224 #include <qcolor.h>
225 #include <qlayout.h>
226 #include <QX11Info>
227 #include <klocale.h>
228 #include <kmessagebox.h>
230 #include "swarm.h"
231 #include "swarm.moc"
232 #include "helpers.h"
234 #undef Below
236 static kSwarmSaver *saver = NULL;
238 void startScreenSaver( Drawable d )
240 if ( saver )
241 return;
242 saver = new kSwarmSaver( d );
245 void stopScreenSaver()
247 if ( saver )
248 delete saver;
249 saver = NULL;
252 int setupScreenSaver()
254 kSwarmSetup dlg;
256 return dlg.exec();
259 //-----------------------------------------------------------------------------
261 kSwarmSaver::kSwarmSaver( Drawable drawable ) : kScreenSaver( drawable )
263 readSettings();
265 // Clear to background colour when exposed
266 XSetWindowBackground(QX11Info::display(), mDrawable,
267 BlackPixel(QX11Info::display(), QX11Info::appScreen()));
269 batchcount = maxLevels;
271 initXLock( mGc );
272 initswarm( mDrawable, rnd );
274 timer.start( speed );
275 connect( &timer, SIGNAL( timeout() ), SLOT( slotTimeout() ) );
278 kSwarmSaver::~kSwarmSaver()
280 timer.stop();
283 void kSwarmSaver::setSpeed( int spd )
285 timer.stop();
286 speed = MAXSPEED - spd;
287 timer.start( speed );
290 void kSwarmSaver::setLevels( int l )
292 batchcount = maxLevels = l;
293 initswarm( mDrawable, rnd );
296 void kSwarmSaver::readSettings()
298 KConfig *config = klock_config();
299 KConfigGroup group = config->group( "Settings" );
301 speed = MAXSPEED - group.readEntry( "Speed", MAXSPEED - DEFSPEED );
302 maxLevels = group.readEntry( "MaxLevels", DEFBATCH );
304 delete config;
307 void kSwarmSaver::slotTimeout()
309 drawswarm( mDrawable, rnd );
312 //-----------------------------------------------------------------------------
314 kSwarmSetup::kSwarmSetup( QWidget *parent, const char *name )
315 : KDialog( parent)
317 setCaption(i18n( "Setup Swarm Screen Saver" ));
318 setButtons(Ok|Cancel|Help);
319 setDefaultButton(Ok);
320 setModal(true);
321 showButtonSeparator(true);
322 readSettings();
324 setButtonText( Help, i18n( "A&bout" ) );
325 QWidget *main = new QWidget(this);
326 setMainWidget(main);
328 QHBoxLayout *top = new QHBoxLayout(main );
329 QVBoxLayout *left = new QVBoxLayout;
330 top->addLayout(left);
332 QLabel *label = new QLabel( i18n("Speed:"), main );
333 min_size(label);
334 left->addWidget(label);
336 QSlider *slider = new QSlider(Qt::Horizontal,main);
337 slider->setMaximum(MAXSPEED);
338 slider->setMinimum(MINSPEED);
339 slider->setValue(speed);
340 slider->setMinimumSize( 120, 20 );
341 slider->setTickPosition(QSlider::TicksBelow);
342 slider->setTickInterval(10);
343 connect( slider, SIGNAL( valueChanged( int ) ),
344 SLOT( slotSpeed( int ) ) );
345 left->addWidget(slider);
347 label = new QLabel( i18n("Number of bees:"), main );
348 min_size(label);
349 left->addWidget(label);
351 slider = new QSlider(Qt::Horizontal,main);
352 slider->setMaximum(MAXBATCH);
353 slider->setMinimum(MINBATCH);
354 slider->setValue(20);
356 slider->setMinimumSize( 120, 20 );
357 slider->setTickPosition(QSlider::TicksBelow);
358 slider->setTickInterval(20);
359 connect( slider, SIGNAL( valueChanged( int ) ),
360 SLOT( slotLevels( int ) ) );
361 left->addWidget(slider);
362 left->addStretch();
364 preview = new QWidget( main );
365 preview->setFixedSize( 220, 170 );
366 QPalette palette = preview->palette();
367 palette.setColor(preview->backgroundRole(), Qt::black);
368 preview->setPalette(palette);
370 preview->show(); // otherwise saver does not get correct size
371 saver = new kSwarmSaver( preview->winId() );
372 top->addWidget(preview);
374 top->addStretch();
375 connect(this,SIGNAL(okClicked()),this,SLOT(slotOk()));
376 connect(this,SIGNAL(helpClicked()),this,SLOT(slotHelp()));
379 void kSwarmSetup::readSettings()
381 KConfig *config = klock_config();
382 KConfigGroup group = config->group( "Settings" );
384 speed = group.readEntry( "Speed", speed );
386 if ( speed > MAXSPEED )
387 speed = MAXSPEED;
388 else if ( speed < MINSPEED )
389 speed = MINSPEED;
391 maxLevels = group.readEntry( "MaxLevels", DEFBATCH );
392 delete config;
395 void kSwarmSetup::slotSpeed( int num )
397 speed = num;
399 if ( saver )
400 saver->setSpeed( speed );
403 void kSwarmSetup::slotLevels( int num )
405 maxLevels = num;
407 if ( saver )
408 saver->setLevels( maxLevels );
411 void kSwarmSetup::slotOk()
413 KConfig *config = klock_config();
414 KConfigGroup group = config->group( "Settings" );
416 QString sspeed;
417 sspeed.setNum( speed );
418 group.writeEntry( "Speed", sspeed );
420 QString slevels;
421 slevels.setNum( maxLevels );
422 group.writeEntry( "MaxLevels", slevels );
424 config->sync();
425 delete config;
426 accept();
429 void kSwarmSetup::slotHelp()
431 KMessageBox::information(this,
432 i18n("Swarm\n\nCopyright (c) 1991 by Patrick J. Naughton\n\nPorted to kscreensaver by Emanuel Pirker."),
433 i18n("About Swarm"));