You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tqt3/examples/tetrix/qdragapp.cpp

503 lines
11 KiB

/****************************************************************************
**
** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
**
** This file is part of an example program for TQt. This example
** program may be used, distributed and modified without limitation.
**
*****************************************************************************/
#include "qdragapp.h"
#include "ntqptrlist.h"
#include "ntqintdict.h"
#include "ntqpopupmenu.h"
#include "ntqguardedptr.h"
#include "ntqcolor.h"
#include "ntqwidget.h"
#include "ntqfontmetrics.h"
#include "ntqcursor.h"
#include "ntqobjectlist.h"
TQWidget *cursorWidget( TQPoint * = 0 );
class TQDragger;
class DropWindow : public TQWidget
{
Q_OBJECT
public:
void paintEvent( TQPaintEvent * );
void closeEvent( TQCloseEvent * );
TQDragger *master;
};
struct DropInfo {
DropInfo() { w=0; }
~DropInfo() { delete w; }
DropWindow *w;
bool userOpened;
};
struct DraggedInfo {
TQWidget *w;
TQWidget *mother;
TQPoint pos;
};
class TQDragger : public TQObject
{
Q_OBJECT
public:
TQDragger();
~TQDragger();
bool notify( TQObject *, TQEvent * ); // event filter
void closeDropWindow( DropWindow * );
public slots:
void openDropWindow();
void killDropWindow();
void killAllDropWindows();
void sendChildHome();
void sendAllChildrenHome();
private:
bool isParentToDragged( TQWidget * );
bool noWidgets( TQWidget * );
void killDropWindow( DropInfo * );
void killAllDropWindows( bool );
void sendChildHome( DraggedInfo * );
void sendAllChildrenHome( TQWidget * );
TQWidget *openDropWindow( const TQRect&, bool );
bool startGrab();
void grabFinished();
bool dragEvent( TQWidget *, TQMouseEvent * );
bool killDropEvent( TQMouseEvent * );
bool sendChildEvent( TQMouseEvent * );
bool killingDrop;
bool sendingChild;
TQWidget *clickedWidget;
TQGuardedPtr<TQWidget> hostWidget;
TQCursor cursor;
TQPopupMenu* menu;
TQPoint clickOffset;
TQColor dragBackground;
TQColor dragForeground;
DraggedInfo dragInfo;
TQIntDict<DraggedInfo> draggedDict;
TQIntDict<DropInfo> dropDict;
};
TQDragApplication::TQDragApplication( int &argc, char **argv )
: TQApplication( argc, argv ), dragger( 0 )
{
dragger = new TQDragger;
}
TQDragApplication::~TQDragApplication()
{
delete dragger;
}
bool TQDragApplication::notify( TQObject *o, TQEvent *e )
{
if ( dragger && !dragger->notify( o, e ) )
return TQApplication::notify( o, e );
else
return FALSE;
}
void DropWindow::paintEvent( TQPaintEvent * )
{
const char *msg = "Drag widgets and drop them here or anywhere!";
int startX = ( width() - fontMetrics().width( msg ) )/2;
startX = startX < 0 ? 0 : startX;
drawText( startX, height()/2, msg );
}
void DropWindow::closeEvent( TQCloseEvent *e )
{
master->closeDropWindow( this );
e->ignore();
}
TQDragger::TQDragger()
{
dragInfo.w = 0;
killingDrop = FALSE;
sendingChild = FALSE;
draggedDict.setAutoDelete( TRUE );
dropDict .setAutoDelete( TRUE );
menu = new TQPopupMenu;
menu->insertItem( "Open drop window", 1 );
menu->insertItem( "Kill drop window", 2 );
menu->insertItem( "Kill all drop windows", 3 );
menu->insertSeparator();
// menu->insertItem( "Send child home", 4 );
menu->insertItem( "Send all children home", 5 );
menu->connectItem( 1, this, SLOT(openDropWindow()) );
menu->connectItem( 2, this, SLOT(killDropWindow()) );
menu->connectItem( 3, this, SLOT(killAllDropWindows()) );
// menu->connectItem( 4, this, SLOT(sendChildHome()) );
menu->connectItem( 5, this, SLOT(sendAllChildrenHome()) );
}
TQDragger::~TQDragger()
{
delete menu;
}
bool TQDragger::notify( TQObject *o, TQEvent *e )
{
if ( !o->isWidgetType() || o == menu )
return FALSE;
switch( e->type() ) {
case TQEvent::MouseMove:
{
TQMouseEvent *tmp = (TQMouseEvent*) e;
if ( killingDrop )
return killDropEvent( tmp );
if ( sendingChild )
return sendChildEvent( tmp );
if ( tmp->state() & TQMouseEvent::RightButton )
return dragEvent( (TQWidget*) o, tmp );
break;
}
case TQEvent::MouseButtonPress:
case TQEvent::MouseButtonRelease:
case TQEvent::MouseButtonDblClick:
{
TQMouseEvent *tmp = (TQMouseEvent*) e;
if ( killingDrop )
return killDropEvent( tmp );
if ( sendingChild )
return sendChildEvent( tmp );
if ( tmp->button() == TQMouseEvent::RightButton )
return dragEvent( (TQWidget*) o, tmp );
}
break;
default:
break;
}
return FALSE;
}
bool TQDragger::isParentToDragged( TQWidget *w )
{
TQIntDictIterator<DraggedInfo> iter( draggedDict );
DraggedInfo *tmp;
while( (tmp = iter.current()) ) {
++iter;
if ( tmp->mother == w )
return TRUE;
}
return FALSE;
}
bool TQDragger::noWidgets( TQWidget *w )
{
const TQObjectList *l = w->children();
if ( !l )
return TRUE;
TQObjectListIt iter( *l );
TQObject *tmp;
while( (tmp = iter.current()) ) {
++iter;
if ( tmp->isWidgetType() )
return FALSE;
}
return TRUE;
}
void TQDragger::sendAllChildrenHome( TQWidget *w )
{
const TQObjectList *l = w->children();
if ( !l )
return;
TQObjectListIt iter( *l );
TQObject *tmp;
while( (tmp = iter.current()) ) {
++iter;
if ( tmp->isWidgetType() ) {
sendAllChildrenHome( (TQWidget*) tmp );
DraggedInfo *di = draggedDict.find( (long) tmp );
if ( di )
sendChildHome( di );
}
}
}
bool TQDragger::dragEvent( TQWidget *w, TQMouseEvent *e )
{
switch( e->type() ) {
case TQEvent::MouseButtonDblClick:
case TQEvent::MouseButtonPress: {
if ( !noWidgets( w ) || // has widget children
isParentToDragged( w ) || // has had widget children
w->parentWidget() == 0 ) { // is top level window
hostWidget = w;
menu->popup( w->mapToGlobal( e->pos() ) );
return TRUE;
}
if ( !draggedDict.find( (long) w ) ) {
DraggedInfo *tmp = new DraggedInfo;
tmp->w = w;
tmp->mother = w->parentWidget();
tmp->pos = w->frameGeometry().topLeft();
draggedDict.insert( (long) w, tmp );
}
dragBackground = w->backgroundColor();
dragForeground = w->foregroundColor();
dragInfo.w = w;
dragInfo.mother = w->parentWidget();
dragInfo.pos = w->frameGeometry().topLeft();
clickOffset = e->pos();
dragInfo.w = w;
TQPoint p = w->mapToGlobal(TQPoint(0,0));
w->reparent( 0, WType_Popup, p, TRUE );
return TRUE;
}
case TQEvent::MouseButtonRelease:
case TQEvent::MouseMove: {
if ( dragInfo.w != 0 ) {
TQPoint p = TQCursor::pos() - clickOffset;
dragInfo.w->move( p );
if ( e->type() == TQEvent::MouseMove )
return TRUE;
} else {
return FALSE;
}
if ( !dragInfo.w )
return FALSE;
if ( w != dragInfo.w )
w = dragInfo.w;
dragInfo.w = 0;
w->hide();
TQPoint pos;
TQWidget *target = cursorWidget( &pos );
pos = pos - clickOffset;
TQPoint p;
if ( !target ) {
target = openDropWindow( TQRect( pos, w->size() ),
FALSE);
p = TQPoint( 0, 0 );
}
else
p = target->mapFromGlobal( pos );
w->reparent( target, 0, p, TRUE );
DropInfo *tmp = dropDict.find( (long) dragInfo.mother );
if ( tmp ) {
if ( !tmp->userOpened && noWidgets( tmp->w ) )
dropDict.remove( (long) tmp->w );
}
if ( !target->isVisible() )
target->show();
}
return TRUE;
default:
return FALSE;
}
}
bool TQDragger::killDropEvent( TQMouseEvent *e )
{
switch( e->type() ) {
case TQEvent::MouseButtonDblClick:
case TQEvent::MouseButtonPress:
clickedWidget = cursorWidget();
return TRUE;
case TQEvent::MouseButtonRelease:
hostWidget->releaseMouse();
if ( clickedWidget ) {
DropInfo *tmp = dropDict.find( (long) clickedWidget );
if( tmp ) {
killDropWindow( tmp );
dropDict.remove( (long) tmp->w );
}
}
grabFinished();
return TRUE;
case TQEvent::MouseMove:
return TRUE;
default:
break;
}
return FALSE;
}
bool TQDragger::sendChildEvent( TQMouseEvent *e )
{
switch( e->type() ) {
case TQEvent::MouseButtonDblClick:
case TQEvent::MouseButtonPress:
clickedWidget = cursorWidget();
return TRUE;
case TQEvent::MouseButtonRelease:
hostWidget->releaseMouse();
if ( clickedWidget ) {
DraggedInfo *tmp = draggedDict.find((long) clickedWidget);
if( tmp ) {
TQWidget *parent = tmp->w->parentWidget();
sendChildHome( tmp );
DropInfo *dri = dropDict.find( (long) parent );
if ( dri && noWidgets(dri->w) && !dri->userOpened ) {
killDropWindow( dri );
dropDict.remove( (long) dri );
}
}
grabFinished();
}
return TRUE;
case TQEvent::MouseMove:
return TRUE;
default:
break;
}
return FALSE;
}
bool TQDragger::startGrab()
{
if ( !hostWidget )
return FALSE;
clickedWidget = 0;
cursor = hostWidget->cursor();
hostWidget->grabMouse();
hostWidget->setCursor( TQCursor( CrossCursor ) );
return TRUE;
}
void TQDragger::grabFinished()
{
killingDrop = FALSE;
sendingChild = FALSE;
if(hostWidget)
hostWidget->setCursor( cursor );
}
void TQDragger::closeDropWindow( DropWindow *w )
{
DropInfo *tmp = dropDict.find( (long) w);
if( tmp )
killDropWindow( tmp );
}
void TQDragger::openDropWindow()
{
TQWidget *tmp = openDropWindow( TQRect(100, 100, 300, 200), TRUE );
tmp->show();
}
TQWidget *TQDragger::openDropWindow( const TQRect &r, bool user )
{
DropInfo *tmp = new DropInfo;
DropWindow *w = new DropWindow;
if ( user ) {
tmp->userOpened = TRUE;
w->setCaption( "Drop window" );
} else {
tmp->userOpened = FALSE;
w->setCaption( "Auto drop window" );
}
tmp->w = w;
w->master = this;
w->setGeometry( r );
dropDict.insert( (long) w, tmp );
w->show();
return w;
}
void TQDragger::killDropWindow()
{
if ( startGrab() )
killingDrop = TRUE;
}
void TQDragger::killDropWindow( DropInfo *di )
{
const TQObjectList *l = di->w->children();
if ( !l )
return;
TQObjectListIt iter( *l );
TQObject *tmp;
while( (tmp = iter.current()) ) {
++iter;
if ( tmp->isWidgetType() ) {
DraggedInfo *dri = draggedDict.find( (long) tmp );
if ( dri ) {
sendChildHome( dri );
draggedDict.remove( (long) tmp );
}
}
}
di->w->hide();
}
void TQDragger::killAllDropWindows()
{
killAllDropWindows( FALSE );
}
void TQDragger::killAllDropWindows( bool autoOnly )
{
TQIntDictIterator<DropInfo> iter( dropDict );
DropInfo *tmp;
while( (tmp = iter.current()) ) {
++iter;
if( !autoOnly || !tmp->userOpened ) {
killDropWindow( tmp );
dropDict.remove( (long) tmp->w );
}
}
}
void TQDragger::sendChildHome( DraggedInfo *i )
{
i->w->reparent( i->mother, 0, i->pos, TRUE );
}
void TQDragger::sendChildHome()
{
if ( startGrab() )
sendingChild = TRUE;
}
void TQDragger::sendAllChildrenHome()
{
TQIntDictIterator<DraggedInfo> iter( draggedDict );
DraggedInfo *tmp;
while( (tmp = iter.current()) ) {
++iter;
sendChildHome( tmp );
draggedDict.remove( (long) tmp->w );
}
killAllDropWindows( TRUE );
draggedDict.clear();
}
TQWidget *cursorWidget( TQPoint *p )
{
TQPoint curpos = TQCursor::pos();
if ( p )
*p = curpos;
return TQApplication::widgetAt( curpos );
}
#include "qdragapp.moc"