summaryrefslogtreecommitdiffstats
path: root/tdescreensaver/xsavers/swarm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tdescreensaver/xsavers/swarm.cpp')
-rw-r--r--tdescreensaver/xsavers/swarm.cpp419
1 files changed, 419 insertions, 0 deletions
diff --git a/tdescreensaver/xsavers/swarm.cpp b/tdescreensaver/xsavers/swarm.cpp
new file mode 100644
index 00000000..b81920ba
--- /dev/null
+++ b/tdescreensaver/xsavers/swarm.cpp
@@ -0,0 +1,419 @@
+/*-
+ * swarm.c - swarm of bees for xlock, the X Window System lockscreen.
+ *
+ * Copyright (c) 1991 by Patrick J. Naughton.
+ *
+ * Revision History:
+ * 31-Aug-90: Adapted from xswarm by Jeff Butterworth. (butterwo@ncsc.org)
+ */
+
+/* Ported to tdescreensaver:
+ July 1997, Emanuel Pirker <epirker@edu.uni-klu.ac.at>
+ Contact me in case of problems, not the original author!
+ Last revised: 10-Jul-97
+*/
+// layout management added 1998/04/19 by Mario Weilguni <mweilguni@kde.org>
+
+#define MAXSPEED 100
+#define MINSPEED 0
+#define DEFSPEED 50
+#define MAXBATCH 200
+#define MINBATCH 0
+#define DEFBATCH 20
+
+#include <tqslider.h>
+#include <kglobal.h>
+#include <kconfig.h>
+#include <krandomsequence.h>
+#include "xlock.h"
+
+#undef index
+
+#define TIMES 4 /* number of time positions recorded */
+#define BEEACC 2 /* acceleration of bees */
+#define WASPACC 5 /* maximum acceleration of wasp */
+#define BEEVEL 12 /* maximum bee velocity */
+#define WASPVEL 10 /* maximum wasp velocity */
+
+/* Macros */
+#define X(t,b) (sp->x[(t)*sp->beecount+(b)])
+#define Y(t,b) (sp->y[(t)*sp->beecount+(b)])
+#define balance_rand(v) (rnd.getLong(v)-((v)/2)) /* random number around 0 */
+
+//ModeSpecOpt swarm_opts = {0, NULL, NULL, NULL};
+
+typedef struct {
+ int pix;
+ int width;
+ int height;
+ int border; /* wasp won't go closer than this to the edge */
+ int beecount; /* number of bees */
+ XSegment segs[MAXBATCH]; /* bee lines */
+ XSegment old_segs[MAXBATCH]; /* old bee lines */
+ short x[MAXBATCH*TIMES];
+ short y[MAXBATCH*TIMES]; /* bee positions x[time][bee#] */
+ short xv[MAXBATCH];
+ short yv[MAXBATCH]; /* bee velocities xv[bee#] */
+ short wx[3];
+ short wy[3];
+ short wxv;
+ short wyv;
+} swarmstruct;
+
+static swarmstruct swarms[MAXSCREENS];
+
+void
+initswarm(Window win, KRandomSequence &rnd)
+{
+ swarmstruct *sp = &swarms[screen];
+ int b;
+ XWindowAttributes xwa;
+
+ sp->beecount = batchcount;
+ (void) XGetWindowAttributes(dsp, win, &xwa);
+ sp->width = xwa.width;
+ sp->height = xwa.height;
+
+ sp->border = (sp->width + sp->height) / 50;
+
+ /* Clear the background. */
+ XSetForeground(dsp, Scr[screen].gc, BlackPixel(dsp, screen));
+ XFillRectangle(dsp, win, Scr[screen].gc, 0, 0, sp->width, sp->height);
+
+ /* Now static data structures. epirker */
+ //if (!sp->segs) {
+ //sp->segs = (XSegment *) malloc(sizeof (XSegment) * sp->beecount);
+ //sp->old_segs = (XSegment *) malloc(sizeof (XSegment) * sp->beecount);
+ //sp->x = (short *) malloc(sizeof (short) * sp->beecount * TIMES);
+ //sp->y = (short *) malloc(sizeof (short) * sp->beecount * TIMES);
+ //sp->xv = (short *) malloc(sizeof (short) * sp->beecount);
+ //sp->yv = (short *) malloc(sizeof (short) * sp->beecount);
+ //}
+ /* Initialize point positions, velocities, etc. */
+
+ /* wasp */
+ sp->wx[0] = sp->border + rnd.getLong(sp->width - 2 * sp->border);
+ sp->wy[0] = sp->border + rnd.getLong(sp->height - 2 * sp->border);
+ sp->wx[1] = sp->wx[0];
+ sp->wy[1] = sp->wy[0];
+ sp->wxv = 0;
+ sp->wyv = 0;
+
+ /* bees */
+ for (b = 0; b < sp->beecount; b++) {
+ X(0, b) = rnd.getLong(sp->width);
+ X(1, b) = X(0, b);
+ Y(0, b) = rnd.getLong(sp->height);
+ Y(1, b) = Y(0, b);
+ sp->xv[b] = balance_rand(7);
+ sp->yv[b] = balance_rand(7);
+ }
+}
+
+
+
+void
+drawswarm(Window win, KRandomSequence &rnd)
+{
+ swarmstruct *sp = &swarms[screen];
+ int b;
+
+ /* <=- Wasp -=> */
+ /* Age the arrays. */
+ sp->wx[2] = sp->wx[1];
+ sp->wx[1] = sp->wx[0];
+ sp->wy[2] = sp->wy[1];
+ sp->wy[1] = sp->wy[0];
+ /* Accelerate */
+ sp->wxv += balance_rand(WASPACC);
+ sp->wyv += balance_rand(WASPACC);
+
+ /* Speed Limit Checks */
+ if (sp->wxv > WASPVEL)
+ sp->wxv = WASPVEL;
+ if (sp->wxv < -WASPVEL)
+ sp->wxv = -WASPVEL;
+ if (sp->wyv > WASPVEL)
+ sp->wyv = WASPVEL;
+ if (sp->wyv < -WASPVEL)
+ sp->wyv = -WASPVEL;
+
+ /* Move */
+ sp->wx[0] = sp->wx[1] + sp->wxv;
+ sp->wy[0] = sp->wy[1] + sp->wyv;
+
+ /* Bounce Checks */
+ if ((sp->wx[0] < sp->border) || (sp->wx[0] > sp->width - sp->border - 1)) {
+ sp->wxv = -sp->wxv;
+ sp->wx[0] += sp->wxv;
+ }
+ if ((sp->wy[0] < sp->border) || (sp->wy[0] > sp->height - sp->border - 1)) {
+ sp->wyv = -sp->wyv;
+ sp->wy[0] += sp->wyv;
+ }
+ /* Don't let things settle down. */
+ sp->xv[rnd.getLong(sp->beecount)] += balance_rand(3);
+ sp->yv[rnd.getLong(sp->beecount)] += balance_rand(3);
+
+ /* <=- Bees -=> */
+ for (b = 0; b < sp->beecount; b++) {
+ int distance, dx, dy;
+
+ /* Age the arrays. */
+ X(2, b) = X(1, b);
+ X(1, b) = X(0, b);
+ Y(2, b) = Y(1, b);
+ Y(1, b) = Y(0, b);
+
+ /* Accelerate */
+ dx = sp->wx[1] - X(1, b);
+ dy = sp->wy[1] - Y(1, b);
+ distance = abs(dx) + abs(dy); /* approximation */
+ if (distance == 0)
+ distance = 1;
+ sp->xv[b] += (dx * BEEACC) / distance;
+ sp->yv[b] += (dy * BEEACC) / distance;
+
+ /* Speed Limit Checks */
+ if (sp->xv[b] > BEEVEL)
+ sp->xv[b] = BEEVEL;
+ if (sp->xv[b] < -BEEVEL)
+ sp->xv[b] = -BEEVEL;
+ if (sp->yv[b] > BEEVEL)
+ sp->yv[b] = BEEVEL;
+ if (sp->yv[b] < -BEEVEL)
+ sp->yv[b] = -BEEVEL;
+
+ /* Move */
+ X(0, b) = X(1, b) + sp->xv[b];
+ Y(0, b) = Y(1, b) + sp->yv[b];
+
+ /* Fill the segment lists. */
+ sp->segs[b].x1 = X(0, b);
+ sp->segs[b].y1 = Y(0, b);
+ sp->segs[b].x2 = X(1, b);
+ sp->segs[b].y2 = Y(1, b);
+ sp->old_segs[b].x1 = X(1, b);
+ sp->old_segs[b].y1 = Y(1, b);
+ sp->old_segs[b].x2 = X(2, b);
+ sp->old_segs[b].y2 = Y(2, b);
+ }
+
+ XSetForeground(dsp, Scr[screen].gc, BlackPixel(dsp, screen));
+ XDrawLine(dsp, win, Scr[screen].gc,
+ sp->wx[1], sp->wy[1], sp->wx[2], sp->wy[2]);
+ XDrawSegments(dsp, win, Scr[screen].gc, sp->old_segs, sp->beecount);
+
+ XSetForeground(dsp, Scr[screen].gc, WhitePixel(dsp, screen));
+ XDrawLine(dsp, win, Scr[screen].gc,
+ sp->wx[0], sp->wy[0], sp->wx[1], sp->wy[1]);
+ if (!mono && Scr[screen].npixels > 2) {
+ XSetForeground(dsp, Scr[screen].gc, Scr[screen].pixels[sp->pix]);
+ if (++sp->pix >= Scr[screen].npixels)
+ sp->pix = 0;
+ }
+ XDrawSegments(dsp, win, Scr[screen].gc, sp->segs, sp->beecount);
+}
+
+//-----------------------------------------------------------------------------
+
+#include <tqcheckbox.h>
+#include <tqlabel.h>
+#include <tqcolor.h>
+#include <tqlayout.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#include "swarm.h"
+#include "swarm.moc"
+#include "helpers.h"
+
+#undef Below
+
+static kSwarmSaver *saver = NULL;
+
+void startScreenSaver( Drawable d )
+{
+ if ( saver )
+ return;
+ saver = new kSwarmSaver( d );
+}
+
+void stopScreenSaver()
+{
+ if ( saver )
+ delete saver;
+ saver = NULL;
+}
+
+int setupScreenSaver()
+{
+ kSwarmSetup dlg;
+
+ return dlg.exec();
+}
+
+//-----------------------------------------------------------------------------
+
+kSwarmSaver::kSwarmSaver( Drawable drawable ) : kScreenSaver( drawable )
+{
+ readSettings();
+
+ // Clear to background colour when exposed
+ XSetWindowBackground(tqt_xdisplay(), mDrawable,
+ BlackPixel(tqt_xdisplay(), tqt_xscreen()));
+
+ colorContext = TQColor::enterAllocContext();
+
+ batchcount = maxLevels;
+
+ initXLock( mGc );
+ initswarm( mDrawable, rnd );
+
+ timer.start( speed );
+ connect( &timer, TQT_SIGNAL( timeout() ), TQT_SLOT( slotTimeout() ) );
+}
+
+kSwarmSaver::~kSwarmSaver()
+{
+ timer.stop();
+ TQColor::leaveAllocContext();
+ TQColor::destroyAllocContext( colorContext );
+}
+
+void kSwarmSaver::setSpeed( int spd )
+{
+ timer.stop();
+ speed = MAXSPEED - spd;
+ timer.start( speed );
+}
+
+void kSwarmSaver::setLevels( int l )
+{
+ batchcount = maxLevels = l;
+ initswarm( mDrawable, rnd );
+}
+
+void kSwarmSaver::readSettings()
+{
+ TDEConfig *config = klock_config();
+ config->setGroup( "Settings" );
+
+ speed = MAXSPEED - config->readNumEntry( "Speed", MAXSPEED - DEFSPEED );
+ maxLevels = config->readNumEntry( "MaxLevels", DEFBATCH );
+
+ delete config;
+}
+
+void kSwarmSaver::slotTimeout()
+{
+ drawswarm( mDrawable, rnd );
+}
+
+//-----------------------------------------------------------------------------
+
+kSwarmSetup::kSwarmSetup( TQWidget *parent, const char *name )
+ : KDialogBase( parent, name, true, i18n( "Setup Swarm Screen Saver" ),
+ Ok|Cancel|Help, Ok, true )
+{
+ readSettings();
+
+ setButtonText( Help, i18n( "A&bout" ) );
+ TQWidget *main = makeMainWidget();
+
+ TQHBoxLayout *top = new TQHBoxLayout( main, 0, spacingHint() );
+ TQVBoxLayout *left = new TQVBoxLayout(top, spacingHint());
+
+ TQLabel *label = new TQLabel( i18n("Speed:"), main );
+ min_size(label);
+ left->addWidget(label);
+
+ TQSlider *slider = new TQSlider(MINSPEED, MAXSPEED, 10, speed,
+ Qt::Horizontal, main );
+ slider->setMinimumSize( 120, 20 );
+ slider->setTickmarks(TQSlider::Below);
+ slider->setTickInterval(10);
+ connect( slider, TQT_SIGNAL( valueChanged( int ) ),
+ TQT_SLOT( slotSpeed( int ) ) );
+ left->addWidget(slider);
+
+ label = new TQLabel( i18n("Number of bees:"), main );
+ min_size(label);
+ left->addWidget(label);
+
+ slider = new TQSlider(MINBATCH, MAXBATCH, 20, maxLevels,Qt::Horizontal, main );
+ slider->setMinimumSize( 120, 20 );
+ slider->setTickmarks(TQSlider::Below);
+ slider->setTickInterval(20);
+ connect( slider, TQT_SIGNAL( valueChanged( int ) ),
+ TQT_SLOT( slotLevels( int ) ) );
+ left->addWidget(slider);
+ left->addStretch();
+
+ preview = new TQWidget( main );
+ preview->setFixedSize( 220, 170 );
+ preview->setBackgroundColor( black );
+ preview->show(); // otherwise saver does not get correct size
+ saver = new kSwarmSaver( preview->winId() );
+ top->addWidget(preview);
+
+ top->addStretch();
+}
+
+void kSwarmSetup::readSettings()
+{
+ TDEConfig *config = klock_config();
+ config->setGroup( "Settings" );
+
+ speed = config->readNumEntry( "Speed", speed );
+
+ if ( speed > MAXSPEED )
+ speed = MAXSPEED;
+ else if ( speed < MINSPEED )
+ speed = MINSPEED;
+
+ maxLevels = config->readNumEntry( "MaxLevels", DEFBATCH );
+ delete config;
+}
+
+void kSwarmSetup::slotSpeed( int num )
+{
+ speed = num;
+
+ if ( saver )
+ saver->setSpeed( speed );
+}
+
+void kSwarmSetup::slotLevels( int num )
+{
+ maxLevels = num;
+
+ if ( saver )
+ saver->setLevels( maxLevels );
+}
+
+void kSwarmSetup::slotOk()
+{
+ TDEConfig *config = klock_config();
+ config->setGroup( "Settings" );
+
+ TQString sspeed;
+ sspeed.setNum( speed );
+ config->writeEntry( "Speed", sspeed );
+
+ TQString slevels;
+ slevels.setNum( maxLevels );
+ config->writeEntry( "MaxLevels", slevels );
+
+ config->sync();
+ delete config;
+ accept();
+}
+
+void kSwarmSetup::slotHelp()
+{
+ KMessageBox::information(this,
+ i18n("Swarm\n\nCopyright (c) 1991 by Patrick J. Naughton\n\nPorted to tdescreensaver by Emanuel Pirker."),
+ i18n("About Swarm"));
+}