| # kdeui Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# kdockwidget.h

    00001 /* This file is part of the KDE libraries
    00002    Copyright (C) 2000 Max Judin <novaprint@mtu-net.ru>
    00003    Copyright (C) 2000 Falk Brettschneider <falk@kdevelop.org>
    00004    Copyright (C) 2002,2003 Joseph Wenninger <jowenn@kde.org>
    00005
    00006    This library is free software; you can redistribute it and/or
    00007    modify it under the terms of the GNU Library General Public
    00008    License version 2 as published by the Free Software Foundation.
    00009
    00010    This library is distributed in the hope that it will be useful,
    00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00013    Library General Public License for more details.
    00014
    00015    You should have received a copy of the GNU Library General Public License
    00016    along with this library; see the file COPYING.LIB.  If not, write to
    00017    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00018    Boston, MA 02111-1307, USA.
    00019 */
    00020
    00021 /*
    00022    activities:
    00023    -----------
    00024    05/2001 -               : useful patches, bugfixes by Christoph Cullmann <crossfire@babylon2k.de>,
    00025                              Joseph Wenninger <jowenn@bigfoot.com> and  Falk Brettschneider
    00026    03/2001 - 05/2001       : maintained and enhanced by Falk Brettschneider <falk@kdevelop.org>
    00027    03/2000                 : class documentation added by Falk Brettschneider <gigafalk@yahoo.com>
    00028    10/1999 - 03/2000       : programmed by Max Judin <novaprint@mtu-net.ru>
    00029
    00030    C++ classes in this file:
    00031    -------------------------
    00032    - KDockWidgetAbstractHeader     - minor helper class
    00033    - KDockWidgetAbstractHeaderDrag - minor helper class
    00034    - KDockWidgetHeaderDrag         - drag panel in a dockwidget title bar
    00035    - KDockWidgetHeader             - dockwidget title bar containing the drag panel
    00036    - KDockTabGroup                 - minor helper class
    00037    - KDockWidget                   - IMPORTANT CLASS: the one and only dockwidget class
    00038    - KDockManager                  - helper class
    00039    - KDockMainWindow               - IMPORTANT CLASS: a special KMainWindow that can have dockwidgets
    00040    - KDockArea                     - like KDockMainWindow but inherits just QWidget
    00041
    00042    IMPORTANT Note: This file compiles also in Qt-only mode by using the NO_KDE2 precompiler definition!
    00043 */
    00044
    00045
    00046 #ifndef KDOCKWIDGET_H
    00047 #define KDOCKWIDGET_H
    00048
    00049 #define _KDOCKWIDGET_2_2_
    00050
    00051 #include <qpoint.h>
    00052 #include <qptrlist.h>
    00053 #include <qframe.h>
    00054 #include <qdom.h>
    00055 #include <qtabwidget.h>
    00056
    00057 #ifndef NO_KDE2
    00058 #include <kmainwindow.h>
    00059 #include <netwm_def.h>
    00060 #else
    00061
    00062 #include <qmainwindow.h>
    00063 #include "exportdockclass.h"
    00064 #include "dummykmainwindow.h"
    00065 #endif
    00066
    00067 class KDockSplitter;
    00068 class KDockManager;
    00069 class KDockMoveManager;
    00070 class KDockWidget;
    00071 class KDockButton_Private;
    00072 class KDockWidgetPrivate;
    00073 class KDockWidgetHeaderPrivate;
    00074 class KDockArea;
    00075
    00076 class QObjectList;
    00077 class QPopupMenu;
    00078 class QVBoxLayout;
    00079 class QHBoxLayout;
    00080 class QPixmap;
    00081
    00082 #ifndef NO_KDE2
    00083 class KToolBar;
    00084 class KConfig;
    00085 #else
    00086 class QToolBar;
    00087 #endif
    00088
    00089 class KDockContainer;
    00090
    00091 namespace KMDI
    00092 {
    00093   class MainWindow;
    00094 }
    00095
    00103 class KDEUI_EXPORT KDockWidgetAbstractHeader : public QFrame
    00104 {
    00105   Q_OBJECT
    00106 public:
    00107
    00114   KDockWidgetAbstractHeader( KDockWidget* parent, const char* name = 0L );
    00115
    00119   virtual ~KDockWidgetAbstractHeader(){};
    00120
    00124   virtual void setTopLevel( bool ){};
    00125
    00126 #ifndef NO_KDE2
    00127
    00130   virtual void saveConfig( KConfig* ){};
    00131
    00135   virtual void loadConfig( KConfig* ){};
    00136 #endif
    00137
    00138 protected:
    00139   virtual void virtual_hook( int id, void* data );
    00140 private:
    00141   class KDockWidgetAbstractHeaderPrivate;
    00142   KDockWidgetAbstractHeaderPrivate *d;
    00143 };
    00144
    00152 class KDEUI_EXPORT KDockWidgetAbstractHeaderDrag : public QFrame
    00153 {
    00154   Q_OBJECT
    00155 public:
    00156
    00164   KDockWidgetAbstractHeaderDrag( KDockWidgetAbstractHeader* parent,
    00165                                  KDockWidget* dock, const char* name = 0L );
    00166
    00170   virtual ~KDockWidgetAbstractHeaderDrag(){};
    00171
    00175   KDockWidget* dockWidget() const { return dw; }
    00176
    00177 private:
    00181   KDockWidget* dw;
    00182 protected:
    00183   virtual void virtual_hook( int id, void* data );
    00184 private:
    00185   class KDockWidgetAbstractHeaderDragPrivate;
    00186   KDockWidgetAbstractHeaderDragPrivate *d;
    00187 };
    00188
    00197 class KDEUI_EXPORT KDockWidgetHeaderDrag : public KDockWidgetAbstractHeaderDrag
    00198 {
    00199   Q_OBJECT
    00200 public:
    00201
    00209   KDockWidgetHeaderDrag( KDockWidgetAbstractHeader* parent, KDockWidget* dock,
    00210                          const char* name = 0L );
    00211
    00215   virtual ~KDockWidgetHeaderDrag(){};
    00216
    00217 protected:
    00218
    00222   virtual void paintEvent( QPaintEvent* );
    00223
    00224 protected:
    00225   virtual void virtual_hook( int id, void* data );
    00226 private:
    00227   class KDockWidgetHeaderDragPrivate;
    00228   KDockWidgetHeaderDragPrivate *d;
    00229 };
    00230
    00238 class KDEUI_EXPORT KDockWidgetHeader : public KDockWidgetAbstractHeader
    00239 {
    00240   Q_OBJECT
    00241 public:
    00242
    00249   KDockWidgetHeader( KDockWidget* parent, const char* name = 0L );
    00250
    00254   virtual ~KDockWidgetHeader(){};
    00255
    00261   virtual void setTopLevel( bool t);
    00262
    00268   void setDragPanel( KDockWidgetHeaderDrag* nd );
    00269
    00275    KDockWidgetHeaderDrag *dragPanel();
    00276
    00277   bool dragEnabled() const;
    00278   void setDragEnabled(bool b);
    00280   void showUndockButton(bool show);
    00281
    00283   void forceCloseButtonHidden(bool enable=true);
    00284 #ifndef NO_KDE2
    00285
    00290   virtual void saveConfig( KConfig* c);
    00291
    00297   virtual void loadConfig( KConfig* c);
    00298 #endif
    00299
    00300    /*@since 3.2
    00301     * add an arbitrary button to the dockwidget header
    00302     * NOT PART OF THE PUBLIC API (you don't have access the class defintion anyways, without special
    00303     * header file copying. (don't do it))
    00304     */
    00305     void addButton(KDockButton_Private*);
    00306
    00307    /*@since 3.2
    00308     * remove an arbtrary button from the dockwidget header
    00309     * NOT PART OF THE PUBLIC API (you don't have access the class defintion anyways, without special
    00310     * header file copying. (don't do it))
    00311     */
    00312     void removeButton(KDockButton_Private*);
    00313
    00314
    00315
    00316 protected slots:
    00320   void slotStayClicked();
    00321
    00322 protected:
    00323
    00327   QHBoxLayout* layout;
    00328
    00332   KDockButton_Private* closeButton;
    00333
    00337   KDockButton_Private* stayButton;
    00338
    00342   KDockButton_Private* dockbackButton;
    00343
    00347   KDockWidgetHeaderDrag* drag;
    00348
    00349 protected:
    00350   virtual void virtual_hook( int id, void* data );
    00351 private:
    00352   KDockWidgetHeaderPrivate *d;
    00353 };
    00354
    00363 class KDEUI_EXPORT KDockTabGroup : public QTabWidget
    00364 {
    00365   Q_OBJECT
    00366 public:
    00370   KDockTabGroup( QWidget *parent = 0, const char *name = 0 )
    00371   :QTabWidget( parent, name ){};
    00372
    00376   virtual ~KDockTabGroup(){};
    00377
    00378   QWidget *transientTo();
    00379 protected:
    00380   virtual void virtual_hook( int id, void* data );
    00381 private:
    00382   class KDockTabGroupPrivate;
    00383   KDockTabGroupPrivate *d;
    00384 };
    00385
    00386
    00423 class KDEUI_EXPORT KDockWidget: public QWidget
    00424 {
    00425   Q_OBJECT
    00426 friend class KDockManager;
    00427 friend class KDockSplitter;
    00428 friend class KDockMainWindow;
    00429 friend class KDockArea;
    00430
    00431 public:
    00447   KDockWidget( KDockManager* dockManager, const char* name,
    00448                const QPixmap &pixmap, QWidget* parent = 0L, const QString& strCaption = QString::null,
    00449                const QString& strTabPageLabel = QString::fromLatin1( " " ), WFlags f = 0);
    00450
    00454   virtual ~KDockWidget();
    00455
    00459   enum DockPosition
    00460   {
    00461     DockNone   = 0,
    00462     DockTop    = 0x0001,
    00463     DockLeft   = 0x0002,
    00464     DockRight  = 0x0004,
    00465     DockBottom = 0x0008,
    00466     DockCenter = 0x0010,
    00467     DockDesktop= 0x0020,
    00468     DockToSpecialSites=0x0040,
    00469     DockCorner = DockTop | DockLeft | DockRight | DockBottom,
    00470     DockFullSite = DockCorner | DockCenter,
    00471     DockFullDocking = DockFullSite | DockDesktop
    00472   };
    00473
    00493   KDockWidget* manualDock( KDockWidget* target, DockPosition dockPos, int spliPos = 50, QPoint pos = QPoint(0,0), bool check = false, int tabIndex = -1);
    00494
    00500   void setEnableDocking( int pos );
    00501
    00505   int enableDocking() const { return eDocking; }
    00506
    00512   void setDockSite( int pos ){ sDocking = pos;}
    00513
    00517   int dockSite() const { return sDocking; }
    00518
    00526   void setWidget( QWidget* w);
    00527
    00533   QWidget* getWidget() const { return widget; };
    00534
    00543   void setHeader( KDockWidgetAbstractHeader* ah);
    00544
    00548   KDockWidgetAbstractHeader *getHeader();
    00549
    00555   void makeDockVisible();
    00556
    00566   bool mayBeHide() const;
    00567
    00575   bool mayBeShow() const;
    00576
    00580   KDockManager* dockManager() const { return manager; }
    00581
    00592   void setToolTipString(const QString& ttStr) { toolTipStr = ttStr; };
    00593
    00597   const QString& toolTipString() const { return toolTipStr; };
    00598
    00602   bool isDockBackPossible() const;
    00603
    00608   void setTabPageLabel( const QString& label) { tabPageTitle = label; };
    00609
    00613   const QString& tabPageLabel() const { return tabPageTitle; };
    00614
    00618   virtual bool event( QEvent * );
    00619
    00623   virtual void show();
    00627   KDockTabGroup* parentDockTabGroup() const;
    00628
    00630   QWidget *parentDockContainer() const;
    00631
    00632 #ifndef NO_KDE2
    00633
    00639   void setDockWindowType (NET::WindowType windowType);
    00640
    00641 #endif
    00642
    00643   void setDockWindowTransient (QWidget *parent, bool transientEnabled);
    00644
    00649    QWidget *transientTo();
    00650
    00657   KDockWidget *findNearestDockWidget(DockPosition pos);
    00658
    00665    void setPixmap(const QPixmap& pixmap=QPixmap());
    00666
    00672    const QPixmap& pixmap() const;
    00673
    00678   KDockWidget::DockPosition currentDockPosition() const;
    00679
    00680 public slots:
    00687   void setForcedFixedWidth(int);
    00694   void setForcedFixedHeight(int);
    00696   void restoreFromForcedFixedSize();
    00697
    00699   int forcedFixedWidth();
    00701   int forcedFixedHeight();
    00702
    00707   void dockBack();
    00708
    00712   void changeHideShowState();
    00713
    00719   void undock();
    00720
    00725   void toDesktop( );
    00726
    00727 protected:
    00728   friend class KMdiMainFrm;
    00729   friend class KMDI::MainWindow;
    00737   void updateHeader();
    00738
    00740   void setLatestKDockContainer(QWidget *);
    00742   QWidget *latestKDockContainer();
    00743
    00745   void setFormerBrotherDockWidget(KDockWidget *);
    00746
    00747 signals:
    00752    void widgetSet(QWidget*);
    00753
    00760   void docking( KDockWidget* dw, KDockWidget::DockPosition dp);
    00761
    00765   void setDockDefaultPos();
    00766
    00770   void headerCloseButtonClicked();
    00771
    00775   void headerDockbackButtonClicked();
    00776
    00780   void iMBeingClosed();
    00784   void hasUndocked();
    00785
    00786 protected slots:
    00787
    00792   void loseFormerBrotherDockWidget();
    00793
    00794   virtual void paintEvent(QPaintEvent*);
    00795
    00796   virtual void mousePressEvent(QMouseEvent*);
    00797   virtual void mouseReleaseEvent(QMouseEvent*);
    00798   virtual void mouseMoveEvent(QMouseEvent*);
    00799   virtual void leaveEvent(QEvent*);
    00800 protected:
    00801   friend class KDockWidgetHeader;
    00805   KDockWidget* formerBrotherDockWidget;
    00809   DockPosition currentDockPos;
    00813   DockPosition formerDockPos;
    00817   QString toolTipStr;
    00821   QString tabPageTitle;
    00822
    00823 private:
    00829   void setDockTabName( KDockTabGroup* g);
    00830
    00838   void applyToWidget( QWidget* s, const QPoint& p  = QPoint(0,0) );
    00839
    00843   KDockWidgetAbstractHeader* header;
    00844
    00848   QWidget* widget;
    00849
    00853   QVBoxLayout* layout;
    00854
    00858   KDockManager* manager;
    00859
    00863   QPixmap* pix;
    00864
    00868   int eDocking;
    00869
    00873   int sDocking;
    00874
    00878   KDockWidget::DockPosition prevSideDockPosBeforeDrag;
    00879
    00880   // GROUP data
    00881   QString firstName;
    00882   QString lastName;
    00883   Orientation splitterOrientation;
    00884   bool isGroup;
    00885   bool isTabGroup;
    00886 protected:
    00887   virtual void virtual_hook( int id, void* data );
    00888 private:
    00889   KDockWidgetPrivate *d;
    00890 };
    00891
    00904 class KDEUI_EXPORT KDockManager: public QObject
    00905 {
    00906   Q_OBJECT
    00907 friend class KDockWidget;
    00908 friend class KDockMainWindow;
    00909
    00910 public:
    00911     enum EnReadDockConfigMode {
    00912         Unknown,
    00913         WrapExistingWidgetsOnly,
    00914         RestoreAllDockwidgets
    00915     };
    00916
    00917 public:
    00928   KDockManager( QWidget* mainWindow, const char* name = 0L );
    00929
    00933   virtual ~KDockManager();
    00934
    00935   void dumpDockWidgets();
    00936
    00937 #ifndef NO_KDE2
    00938
    00947   void writeConfig( KConfig* c = 0L, QString group = QString::null );
    00948
    00965   void readConfig ( KConfig* c = 0L, QString group = QString::null );
    00966 #endif
    00967
    00969   void setMainDockWidget2(KDockWidget *);
    00970
    00974   void writeConfig(QDomElement &base);
    00978   void readConfig(QDomElement &base);
    00979
    00984   void activate();
    00985
    00994   virtual bool eventFilter( QObject * object, QEvent * event );
    00995
    01003   KDockWidget* findWidgetParentDock( QWidget* w) const;
    01004
    01010   void makeWidgetDockVisible( QWidget* w ){ findWidgetParentDock(w)->makeDockVisible(); }
    01011
    01015   QPopupMenu* dockHideShowMenu() const { return menu; }
    01016
    01021   KDockWidget* getDockWidgetFromName( const QString& dockName );
    01022
    01027   void setSplitterOpaqueResize(bool b=true);
    01028
    01032   bool splitterOpaqueResize() const;
    01033
    01039   void setSplitterKeepSize(bool b=true);
    01040
    01044   bool splitterKeepSize() const;
    01045
    01052   void setSplitterHighResolution(bool b=true);
    01053
    01057   bool splitterHighResolution() const;
    01058
    01062   void setSpecialLeftDockContainer(KDockWidget* container);
    01063   void setSpecialTopDockContainer(KDockWidget* container);
    01064   void setSpecialRightDockContainer(KDockWidget* container);
    01065   void setSpecialBottomDockContainer(KDockWidget* container);
    01066
    01067   void removeFromAutoCreateList(KDockWidget* pDockWidget);
    01068   void finishReadDockConfig();
    01069   void setReadDockConfigMode(int mode);
    01070
    01071 signals:
    01072
    01076   void change();
    01077
    01081   void replaceDock( KDockWidget* oldDock, KDockWidget* newDock );
    01082
    01086   void setDockDefaultPos( KDockWidget* );
    01087
    01088 private slots:
    01089
    01093   void slotMenuPopup();
    01094
    01100   void slotMenuActivated( int id);
    01101
    01102   /* clears the old drawn drag rectangle (oldDragRect) from screen and
    01103    * draws the new current drag rectangle (dragRect) depending on the current mouse position.
    01104    * This highlights the dockwidget which is the currently chosen target during a dock action.
    01105    */
    01106   void drawDragRectangle();
    01107
    01108 private:
    01109
    01113   struct MenuDockData
    01114   {
    01115     MenuDockData( KDockWidget* _dock, bool _hide )
    01116     {
    01117       dock = _dock;
    01118       hide = _hide;
    01119     };
    01120     ~MenuDockData(){};
    01121
    01122     KDockWidget* dock;
    01123     bool hide;
    01124   };
    01125
    01132   KDockWidget* findDockWidgetAt( const QPoint& pos );
    01133
    01141   void findChildDockWidget( QWidget*& w, const QWidget* p, const QPoint& pos );
    01142
    01149   void findChildDockWidget( const QWidget* p, QWidgetList*& l);
    01150
    01154   void startDrag( KDockWidget* );
    01155
    01162   void dragMove( KDockWidget* d, QPoint pos );
    01163
    01167   void cancelDrop();
    01168
    01173   void drop();
    01174
    01175 // class members
    01176
    01180   QWidget* main;
    01181
    01185   KDockWidget* currentDragWidget;
    01186
    01190   KDockWidget* currentMoveWidget; // widget where mouse moving
    01191
    01195   QWidgetList* childDockWidgetList;
    01196
    01200   KDockWidget::DockPosition curPos;
    01201
    01206   QObjectList* childDock;
    01207
    01211   QObjectList* autoCreateDock;
    01212
    01216   int storeW;
    01217
    01221   int storeH;
    01222
    01226   bool dragging;
    01227
    01231   bool undockProcess;
    01232
    01237   bool dropCancel;
    01238
    01243   QPopupMenu* menu;
    01244
    01248   QPtrList<MenuDockData> *menuData;
    01249
    01250 protected:
    01251   virtual void virtual_hook( int id, void* data );
    01252 private:
    01253   class KDockManagerPrivate;
    01254   KDockManagerPrivate *d;
    01255 };
    01256
    01300 class KDEUI_EXPORT KDockMainWindow : public KMainWindow
    01301 {
    01302   Q_OBJECT
    01303
    01304 friend class KDockManager;
    01305
    01306 public:
    01307
    01320   KDockMainWindow( QWidget* parent = 0L, const char *name = 0L, WFlags f = WType_TopLevel | WDestructiveClose );
    01321
    01325   virtual ~KDockMainWindow();
    01326
    01331   KDockManager* manager() const { return dockManager; }
    01332
    01339   void setMainDockWidget( KDockWidget* dockwidget);
    01340
    01346   KDockWidget* getMainDockWidget() const { return mainDockWidget; }
    01347
    01360   KDockWidget* createDockWidget( const QString& name, const QPixmap &pixmap, QWidget* parent = 0L,
    01361     const QString& strCaption = QString::null, const QString& strTabPageLabel = QString::fromLatin1( " " ) );
    01362
    01366   void writeDockConfig(QDomElement &base);
    01370   void readDockConfig(QDomElement &base);
    01371
    01372 #ifndef NO_KDE2
    01373
    01379   void writeDockConfig( KConfig* c = 0L, QString group = QString::null );
    01380
    01387   void readDockConfig ( KConfig* c = 0L, QString group = QString::null );
    01388 #endif
    01389
    01395   void activateDock(){ dockManager->activate(); }
    01396
    01403   QPopupMenu* dockHideShowMenu() const { return dockManager->dockHideShowMenu(); }
    01404
    01412   void makeDockVisible( KDockWidget* dock );
    01413
    01419   void makeDockInvisible( KDockWidget* dock );
    01420
    01425   void makeWidgetDockVisible( QWidget* widget );
    01426
    01433   void setView( QWidget * widget );
    01434
    01435 signals:
    01439   void dockWidgetHasUndocked(KDockWidget*);
    01440
    01441 protected:
    01442
    01446   KDockWidget* mainDockWidget;
    01447
    01451   KDockManager* dockManager;
    01452
    01453 protected slots:
    01457   void slotDockWidgetUndocked();
    01458
    01459 protected:
    01460   virtual void virtual_hook( int id, void* data );
    01461 private:
    01462   class KDockMainWindowPrivate;
    01463   KDockMainWindowPrivate *d;
    01464 };
    01465
    01466 class KDEUI_EXPORT KDockArea : public QWidget
    01467 {
    01468   Q_OBJECT
    01469
    01470 friend class KDockManager;
    01471
    01472 public:
    01473
    01474
    01475   KDockArea( QWidget* parent = 0L, const char *name = 0L);
    01476
    01477   virtual ~KDockArea();
    01478
    01479   KDockManager* manager(){ return dockManager; }
    01480
    01481
    01482   void setMainDockWidget( KDockWidget* );
    01483   KDockWidget* getMainDockWidget(){ return mainDockWidget; }
    01484
    01485   KDockWidget* createDockWidget( const QString& name, const QPixmap &pixmap, QWidget* parent = 0L,
    01486     const QString& strCaption = QString::null, const QString& strTabPageLabel = QString::fromLatin1( " " ) );
    01487
    01488   void writeDockConfig(QDomElement &base);
    01489   void readDockConfig(QDomElement &base);
    01490
    01491 #ifndef NO_KDE2
    01492   void writeDockConfig( KConfig* c = 0L, QString group = QString::null );
    01493   void readDockConfig ( KConfig* c = 0L, QString group = QString::null );
    01494 #endif
    01495
    01496
    01497
    01498   void activateDock(){ dockManager->activate(); }
    01499   QPopupMenu* dockHideShowMenu(){ return dockManager->dockHideShowMenu(); }
    01500   void makeDockVisible( KDockWidget* dock );
    01501   void makeDockInvisible( KDockWidget* dock );
    01502   void makeWidgetDockVisible( QWidget* widget );
    01503   //void setView( QWidget* );
    01504
    01505 signals:
    01509   void dockWidgetHasUndocked(KDockWidget*);
    01510
    01511 protected:
    01512
    01513   KDockWidget* mainDockWidget;
    01514   KDockManager* dockManager;
    01515
    01516 protected slots:
    01517   void slotDockWidgetUndocked();
    01518
    01519 public:
    01520     virtual void resizeEvent(QResizeEvent *);
    01521
    01522 protected:
    01523   virtual void virtual_hook( int id, void* data );
    01524 private:
    01525   class KDockMainWindowPrivate;
    01526   KDockMainWindowPrivate *d;
    01527 };
    01528
    01529
    01530 #endif
    01531
    01532

This file is part of the documentation for kdeui Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:20:16 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003