diff options
Diffstat (limited to 'src/widgets/qwidgetresizehandler.cpp')
-rw-r--r-- | src/widgets/qwidgetresizehandler.cpp | 516 |
1 files changed, 516 insertions, 0 deletions
diff --git a/src/widgets/qwidgetresizehandler.cpp b/src/widgets/qwidgetresizehandler.cpp new file mode 100644 index 000000000..6ce1e7789 --- /dev/null +++ b/src/widgets/qwidgetresizehandler.cpp @@ -0,0 +1,516 @@ +/**************************************************************************** +** +** Implementation of the TQWidgetResizeHandler class +** +** Created : 001010 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the workspace module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qwidgetresizehandler_p.h" + +#ifndef QT_NO_RESIZEHANDLER +#include "qframe.h" +#include "qapplication.h" +#include "qcursor.h" +#include "qsizegrip.h" +#if defined(Q_WS_WIN) +#include "qt_windows.h" +#endif + +#define RANGE 4 + +static bool resizeHorizontalDirectionFixed = FALSE; +static bool resizeVerticalDirectionFixed = FALSE; + +TQWidgetResizeHandler::TQWidgetResizeHandler( TQWidget *parent, TQWidget *cw, const char *name ) + : TQObject( parent, name ), widget( parent ), childWidget( cw ? cw : parent ), + extrahei( 0 ), buttonDown( FALSE ), moveResizeMode( FALSE ), sizeprotect( TRUE ), moving( TRUE ) +{ + mode = Nowhere; + widget->setMouseTracking( TRUE ); + TQFrame *frame = ::qt_cast<TQFrame*>(widget); + range = frame ? frame->frameWidth() : RANGE; + range = TQMAX( RANGE, range ); + activeForMove = activeForResize = TRUE; + qApp->installEventFilter( this ); +} + +void TQWidgetResizeHandler::setActive( Action ac, bool b ) +{ + if ( ac & Move ) + activeForMove = b; + if ( ac & Resize ) + activeForResize = b; + + if ( !isActive() ) + setMouseCursor( Nowhere ); +} + +bool TQWidgetResizeHandler::isActive( Action ac ) const +{ + bool b = FALSE; + if ( ac & Move ) b = activeForMove; + if ( ac & Resize ) b |= activeForResize; + + return b; +} + +static TQWidget *childOf( TQWidget *w, TQWidget *child ) +{ + while ( child ) { + if ( child == w ) + return child; + if ( child->isTopLevel() ) + break; + child = child->parentWidget(); + } + return 0; +} + +bool TQWidgetResizeHandler::eventFilter( TQObject *o, TQEvent *ee ) +{ + if ( !isActive() || !o->isWidgetType() || !ee->spontaneous()) + return FALSE; + + if ( ee->type() != TQEvent::MouseButtonPress && + ee->type() != TQEvent::MouseButtonRelease && + ee->type() != TQEvent::MouseMove && + ee->type() != TQEvent::KeyPress && + ee->type() != TQEvent::AccelOverride ) + return FALSE; + + TQWidget *w = childOf( widget, (TQWidget*)o ); + if ( !w +#ifndef QT_NO_SIZEGRIP + || ::qt_cast<TQSizeGrip*>(o) +#endif + || qApp->activePopupWidget() ) { + if ( buttonDown && ee->type() == TQEvent::MouseButtonRelease ) + buttonDown = FALSE; + return FALSE; + } + + TQMouseEvent *e = (TQMouseEvent*)ee; + switch ( e->type() ) { + case TQEvent::MouseButtonPress: { + if ( w->isMaximized() ) + break; + if ( !widget->rect().contains( widget->mapFromGlobal( e->globalPos() ) ) ) + return FALSE; + if ( e->button() == LeftButton ) { + emit activate(); + bool me = isMovingEnabled(); + setMovingEnabled( me && o == widget ); + mouseMoveEvent( e ); + setMovingEnabled( me ); + buttonDown = TRUE; + moveOffset = widget->mapFromGlobal( e->globalPos() ); + invertedMoveOffset = widget->rect().bottomRight() - moveOffset; + } + } break; + case TQEvent::MouseButtonRelease: + if ( w->isMaximized() ) + break; + if ( e->button() == LeftButton ) { + moveResizeMode = FALSE; + buttonDown = FALSE; + widget->releaseMouse(); + widget->releaseKeyboard(); + } + break; + case TQEvent::MouseMove: { + if ( w->isMaximized() ) + break; + bool me = isMovingEnabled(); + setMovingEnabled( me && o == widget ); + mouseMoveEvent( e ); + setMovingEnabled( me ); + if ( buttonDown && mode != Center ) + return TRUE; + } break; + case TQEvent::KeyPress: + keyPressEvent( (TQKeyEvent*)e ); + break; + case TQEvent::AccelOverride: + if ( buttonDown ) { + ((TQKeyEvent*)ee)->accept(); + return TRUE; + } + break; + default: + break; + } + return FALSE; +} + +void TQWidgetResizeHandler::mouseMoveEvent( TQMouseEvent *e ) +{ + TQPoint pos = widget->mapFromGlobal( e->globalPos() ); + if ( !moveResizeMode && ( !buttonDown || ( e->state() & LeftButton ) == 0 ) ) { + if ( pos.y() <= range && pos.x() <= range) + mode = TopLeft; + else if ( pos.y() >= widget->height()-range && pos.x() >= widget->width()-range) + mode = BottomRight; + else if ( pos.y() >= widget->height()-range && pos.x() <= range) + mode = BottomLeft; + else if ( pos.y() <= range && pos.x() >= widget->width()-range) + mode = TopRight; + else if ( pos.y() <= range ) + mode = Top; + else if ( pos.y() >= widget->height()-range ) + mode = Bottom; + else if ( pos.x() <= range ) + mode = Left; + else if ( pos.x() >= widget->width()-range ) + mode = Right; + else + mode = Center; + + if ( widget->isMinimized() || !isActive(Resize) ) + mode = Center; +#ifndef QT_NO_CURSOR + setMouseCursor( mode ); +#endif + return; + } + + if ( buttonDown && !isMovingEnabled() && mode == Center && !moveResizeMode ) + return; + + if ( widget->testWState( WState_ConfigPending ) ) + return; + + TQPoint globalPos = widget->parentWidget( TRUE ) ? + widget->parentWidget( TRUE )->mapFromGlobal( e->globalPos() ) : e->globalPos(); + if ( widget->parentWidget( TRUE ) && !widget->parentWidget( TRUE )->rect().contains( globalPos ) ) { + if ( globalPos.x() < 0 ) + globalPos.rx() = 0; + if ( globalPos.y() < 0 ) + globalPos.ry() = 0; + if ( sizeprotect && globalPos.x() > widget->parentWidget()->width() ) + globalPos.rx() = widget->parentWidget()->width(); + if ( sizeprotect && globalPos.y() > widget->parentWidget()->height() ) + globalPos.ry() = widget->parentWidget()->height(); + } + + TQPoint p = globalPos + invertedMoveOffset; + TQPoint pp = globalPos - moveOffset; + + int fw = 0; + int mw = TQMAX( childWidget->minimumSizeHint().width(), + childWidget->minimumWidth() ); + int mh = TQMAX( childWidget->minimumSizeHint().height(), + childWidget->minimumHeight() ); + if ( childWidget != widget ) { + TQFrame *frame = ::qt_cast<TQFrame*>(widget); + if ( frame ) + fw = frame->frameWidth(); + mw += 2 * fw; + mh += 2 * fw + extrahei; + } + + TQSize mpsize( widget->geometry().right() - pp.x() + 1, + widget->geometry().bottom() - pp.y() + 1 ); + mpsize = mpsize.expandedTo( widget->minimumSize() ).expandedTo( TQSize(mw, mh) ); + TQPoint mp( widget->geometry().right() - mpsize.width() + 1, + widget->geometry().bottom() - mpsize.height() + 1 ); + + TQRect geom = widget->geometry(); + + switch ( mode ) { + case TopLeft: + geom = TQRect( mp, widget->geometry().bottomRight() ) ; + break; + case BottomRight: + geom = TQRect( widget->geometry().topLeft(), p ) ; + break; + case BottomLeft: + geom = TQRect( TQPoint(mp.x(), widget->geometry().y() ), TQPoint( widget->geometry().right(), p.y()) ) ; + break; + case TopRight: + geom = TQRect( TQPoint( widget->geometry().x(), mp.y() ), TQPoint( p.x(), widget->geometry().bottom()) ) ; + break; + case Top: + geom = TQRect( TQPoint( widget->geometry().left(), mp.y() ), widget->geometry().bottomRight() ) ; + break; + case Bottom: + geom = TQRect( widget->geometry().topLeft(), TQPoint( widget->geometry().right(), p.y() ) ) ; + break; + case Left: + geom = TQRect( TQPoint( mp.x(), widget->geometry().top() ), widget->geometry().bottomRight() ) ; + break; + case Right: + geom = TQRect( widget->geometry().topLeft(), TQPoint( p.x(), widget->geometry().bottom() ) ) ; + break; + case Center: + if ( isMovingEnabled() || moveResizeMode ) + geom.moveTopLeft( pp ); + break; + default: + break; + } + + TQSize maxsize( childWidget->maximumSize() ); + if ( childWidget != widget ) + maxsize += TQSize( 2 * fw, 2 * fw + extrahei ); + + geom = TQRect( geom.topLeft(), + geom.size().expandedTo( widget->minimumSize() ) + .expandedTo( TQSize(mw, mh) ) + .boundedTo( maxsize ) ); + + if ( geom != widget->geometry() && + ( widget->isTopLevel() || widget->parentWidget()->rect().intersects( geom ) ) ) { + if ( widget->isMinimized() ) + widget->move( geom.topLeft() ); + else + widget->setGeometry( geom ); + } + +#if defined(Q_WS_WIN) + MSG msg; + QT_WA( { + while(PeekMessageW( &msg, widget->winId(), WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE )) + ; + } , { + while(PeekMessageA( &msg, widget->winId(), WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE )) + ; + } ); +#endif + + TQApplication::syncX(); +} + +void TQWidgetResizeHandler::setMouseCursor( MousePosition m ) +{ +#ifndef QT_NO_CURSOR + switch ( m ) { + case TopLeft: + case BottomRight: + widget->setCursor( sizeFDiagCursor ); + break; + case BottomLeft: + case TopRight: + widget->setCursor( sizeBDiagCursor ); + break; + case Top: + case Bottom: + widget->setCursor( sizeVerCursor ); + break; + case Left: + case Right: + widget->setCursor( sizeHorCursor ); + break; + default: + widget->setCursor( arrowCursor ); + break; + } +#endif +} + +void TQWidgetResizeHandler::keyPressEvent( TQKeyEvent * e ) +{ + if ( !isMove() && !isResize() ) + return; + bool is_control = e->state() & ControlButton; + int delta = is_control?1:8; + TQPoint pos = TQCursor::pos(); + switch ( e->key() ) { + case Key_Left: + pos.rx() -= delta; + if ( pos.x() <= TQApplication::desktop()->geometry().left() ) { + if ( mode == TopLeft || mode == BottomLeft ) { + moveOffset.rx() += delta; + invertedMoveOffset.rx() += delta; + } else { + moveOffset.rx() -= delta; + invertedMoveOffset.rx() -= delta; + } + } + if ( isResize() && !resizeHorizontalDirectionFixed ) { + resizeHorizontalDirectionFixed = TRUE; + if ( mode == BottomRight ) + mode = BottomLeft; + else if ( mode == TopRight ) + mode = TopLeft; +#ifndef QT_NO_CURSOR + setMouseCursor( mode ); + widget->grabMouse( widget->cursor() ); +#else + widget->grabMouse(); +#endif + } + break; + case Key_Right: + pos.rx() += delta; + if ( pos.x() >= TQApplication::desktop()->geometry().right() ) { + if ( mode == TopRight || mode == BottomRight ) { + moveOffset.rx() += delta; + invertedMoveOffset.rx() += delta; + } else { + moveOffset.rx() -= delta; + invertedMoveOffset.rx() -= delta; + } + } + if ( isResize() && !resizeHorizontalDirectionFixed ) { + resizeHorizontalDirectionFixed = TRUE; + if ( mode == BottomLeft ) + mode = BottomRight; + else if ( mode == TopLeft ) + mode = TopRight; +#ifndef QT_NO_CURSOR + setMouseCursor( mode ); + widget->grabMouse( widget->cursor() ); +#else + widget->grabMouse(); +#endif + } + break; + case Key_Up: + pos.ry() -= delta; + if ( pos.y() <= TQApplication::desktop()->geometry().top() ) { + if ( mode == TopLeft || mode == TopRight ) { + moveOffset.ry() += delta; + invertedMoveOffset.ry() += delta; + } else { + moveOffset.ry() -= delta; + invertedMoveOffset.ry() -= delta; + } + } + if ( isResize() && !resizeVerticalDirectionFixed ) { + resizeVerticalDirectionFixed = TRUE; + if ( mode == BottomLeft ) + mode = TopLeft; + else if ( mode == BottomRight ) + mode = TopRight; +#ifndef QT_NO_CURSOR + setMouseCursor( mode ); + widget->grabMouse( widget->cursor() ); +#else + widget->grabMouse(); +#endif + } + break; + case Key_Down: + pos.ry() += delta; + if ( pos.y() >= TQApplication::desktop()->geometry().bottom() ) { + if ( mode == BottomLeft || mode == BottomRight ) { + moveOffset.ry() += delta; + invertedMoveOffset.ry() += delta; + } else { + moveOffset.ry() -= delta; + invertedMoveOffset.ry() -= delta; + } + } + if ( isResize() && !resizeVerticalDirectionFixed ) { + resizeVerticalDirectionFixed = TRUE; + if ( mode == TopLeft ) + mode = BottomLeft; + else if ( mode == TopRight ) + mode = BottomRight; +#ifndef QT_NO_CURSOR + setMouseCursor( mode ); + widget->grabMouse( widget->cursor() ); +#else + widget->grabMouse(); +#endif + } + break; + case Key_Space: + case Key_Return: + case Key_Enter: + case Key_Escape: + moveResizeMode = FALSE; + widget->releaseMouse(); + widget->releaseKeyboard(); + buttonDown = FALSE; + break; + default: + return; + } + TQCursor::setPos( pos ); +} + + +void TQWidgetResizeHandler::doResize() +{ + if ( !activeForResize ) + return; + + moveResizeMode = TRUE; + buttonDown = TRUE; + moveOffset = widget->mapFromGlobal( TQCursor::pos() ); + if ( moveOffset.x() < widget->width()/2) { + if ( moveOffset.y() < widget->height()/2) + mode = TopLeft; + else + mode = BottomLeft; + } else { + if ( moveOffset.y() < widget->height()/2) + mode = TopRight; + else + mode = BottomRight; + } + invertedMoveOffset = widget->rect().bottomRight() - moveOffset; +#ifndef QT_NO_CURSOR + setMouseCursor( mode ); + widget->grabMouse( widget->cursor() ); +#else + widget->grabMouse(); +#endif + widget->grabKeyboard(); + resizeHorizontalDirectionFixed = FALSE; + resizeVerticalDirectionFixed = FALSE; +} + +void TQWidgetResizeHandler::doMove() +{ + if ( !activeForMove ) + return; + + mode = Center; + moveResizeMode = TRUE; + buttonDown = TRUE; + moveOffset = widget->mapFromGlobal( TQCursor::pos() ); + invertedMoveOffset = widget->rect().bottomRight() - moveOffset; +#ifndef QT_NO_CURSOR + widget->grabMouse( SizeAllCursor ); +#else + widget->grabMouse(); +#endif + widget->grabKeyboard(); +} + +#endif //QT_NO_RESIZEHANDLER |