⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bardragpl.cpp

📁 Wxpython Implemented on Windows CE, Source code
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/////////////////////////////////////////////////////////////////////////////
// Name:        bardragpl.cpp
// Purpose:     cbBarDragPlugin implementation
// Author:      Aleksandras Gluchovas
// Modified by:
// Created:     23/09/98
// RCS-ID:      $Id: bardragpl.cpp,v 1.10 2005/09/23 12:47:41 MR Exp $
// Copyright:   (c) Aleksandras Gluchovas
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "wx/fl/bardragpl.h"

#define POS_UNDEFINED -32768

// helpers, FOR NOW:: static

static inline bool rect_hits_rect( const wxRect& r1, const wxRect& r2 )
{
    if ( ( r2.x >= r1.x && r2.x <= r1.x + r1.width ) ||
         ( r1.x >= r2.x && r1.x <= r2.x + r2.width ) )
        if ( ( r2.y >= r1.y && r2.y <= r1.y + r1.height ) ||
             ( r1.y >= r2.y && r1.y <= r2.y + r2.height ) )
            return true;
    return false;
}

static inline bool rect_contains_point( const wxRect& rect, int x, int y )
{
    return ( x >= rect.x &&
             y >= rect.y &&
             x <  rect.x + rect.width  &&
             y <  rect.y + rect.height );
}

/***** Implementation for class cbBarDragPlugin *****/

IMPLEMENT_DYNAMIC_CLASS( cbBarDragPlugin, cbPluginBase )

BEGIN_EVENT_TABLE( cbBarDragPlugin, cbPluginBase )

    //EVT_PL_LEFT_DOWN        ( cbBarDragPlugin::OnLButtonDown      )
    EVT_PL_LEFT_UP            ( cbBarDragPlugin::OnLButtonUp        )
    EVT_PL_MOTION             ( cbBarDragPlugin::OnMouseMove        )
    EVT_PL_DRAW_HINT_RECT     ( cbBarDragPlugin::OnDrawHintRect     )
    EVT_PL_START_BAR_DRAGGING ( cbBarDragPlugin::OnStartBarDragging )
    EVT_PL_LEFT_DCLICK        ( cbBarDragPlugin::OnLDblClick        )

END_EVENT_TABLE()

cbBarDragPlugin::cbBarDragPlugin(void)

    : mBarDragStarted    ( false ),
      mCanStick          ( true ),
      mpScrDc            ( NULL ),
      mpCurCursor        ( NULL ),
      mpDraggedBar       ( NULL ),
      mInClientHintBorder( 4 )
{}

cbBarDragPlugin::cbBarDragPlugin( wxFrameLayout* pPanel, int paneMask )

    : cbPluginBase( pPanel, paneMask ),

      mBarDragStarted    ( false ),
      mCanStick          ( true ),
      mpScrDc            ( NULL ),
      mpCurCursor        ( NULL ),
      mpDraggedBar       ( NULL ),
      mInClientHintBorder( 4 )
{}

cbBarDragPlugin::~cbBarDragPlugin()
{
    // nothing
}

// helper methods (protected)

// clips (top/bottom) or (right/left) edges against the frame's bounding rect.

void do_clip_edges( int len, int& rectPos, int& rectLen )
{
    if ( rectPos < 0 )
    {
        rectLen += rectPos;
        rectPos = 0;
        if ( rectLen < 0 )
            rectLen = 1;
    }
    else
        if ( rectPos > len-1 )
        {
            rectPos = len-1;
            rectLen = 1;
        }
        else
            if ( rectPos + rectLen - 1 > len )
                 rectLen -= (rectPos + rectLen) - len + 1;
}

void cbBarDragPlugin::ClipRectInFrame( wxRect& rect )
{
    int w, h;
    mpLayout->GetParentFrame().GetClientSize( &w, &h );

    do_clip_edges( w, rect.x, rect.width  );
    do_clip_edges( h, rect.y, rect.height );
}

void cbBarDragPlugin::ClipPosInFrame( wxPoint& pos )
{
    int w, h;
    mpLayout->GetParentFrame().GetClientSize( &w, &h );

    if ( pos.x < 0 )
        pos.x = 0;
    if ( pos.y < 0 )
        pos.y = 0;
    if ( pos.x > w )
        pos.x = w-1;
    if ( pos.y > h )
        pos.y = h-1;
}

void cbBarDragPlugin::AdjustHintRect( wxPoint& mousePos )
{
    mHintRect.x = mousePos.x - mMouseInRectX;
    mHintRect.y = mousePos.y - mMouseInRectY;
}

cbDockPane* cbBarDragPlugin::HitTestPanes( wxRect& rect )
{
    //wxRect clipped = rect;

    //ClipRectInFrame( clipped );

    cbDockPane** pPanes = mpLayout->GetPanesArray();

    for( int i = 0; i != MAX_PANES; ++i )
        if ( rect_hits_rect( pPanes[i]->mBoundsInParent, rect ) )
            return pPanes[i];

    return NULL;
}

cbDockPane* cbBarDragPlugin::HitTestPanes( wxPoint& pos )
{
    wxPoint clipped = pos;

    //ClipPosInFrame( pos );

    cbDockPane** pPanes = mpLayout->GetPanesArray();

    for( int i = 0; i != MAX_PANES; ++i )
        if ( rect_contains_point( pPanes[i]->mBoundsInParent, clipped.x, clipped.y ) )
            return pPanes[i];

    return NULL;
}

bool cbBarDragPlugin::HitsPane( cbDockPane* pPane, wxRect& rect )
{
    return rect_hits_rect( pPane->mBoundsInParent, rect );
}

int cbBarDragPlugin::GetDistanceToPane( cbDockPane* pPane, wxPoint& mousePos )
{
    wxRect& bounds = pPane->mBoundsInParent;

    switch( pPane->mAlignment )
    {
        case FL_ALIGN_TOP    : return mousePos.y - ( bounds.y + bounds.height );
        case FL_ALIGN_BOTTOM : return bounds.y - mousePos.y;
        case FL_ALIGN_LEFT   : return mousePos.x - ( bounds.x + bounds.width  );
        case FL_ALIGN_RIGHT  : return bounds.x - mousePos.x;
        default : return 0; // never reached
    }

//    return 0;
}

bool cbBarDragPlugin::IsInOtherPane( wxPoint& mousePos )
{
    cbDockPane* pPane = HitTestPanes( mousePos );

    if ( pPane && pPane != mpCurPane ) return true;
    else return false;
}

bool cbBarDragPlugin::IsInClientArea( wxPoint& mousePos )
{
    return  ( HitTestPanes( mousePos ) == NULL );
}

bool cbBarDragPlugin::IsInClientArea( wxRect& rect )
{
    return ( HitTestPanes( rect ) == NULL );
}

void cbBarDragPlugin::CalcOnScreenDims( wxRect& rect )
{
    if ( !mpCurPane || mpDraggedBar->IsFixed() ) return;

    wxRect inPane = rect;

    mpCurPane->FrameToPane( &inPane );

    int rowNo = mpCurPane->GetRowAt( inPane.y, inPane.y + inPane.height );

    bool isMaximized = ( rowNo >= (int)mpCurPane->GetRowList().Count() || rowNo < 0 );

    if ( isMaximized )
    {
        inPane.x = 0;
        inPane.width = mpCurPane->mPaneWidth;

        mpCurPane->PaneToFrame( &inPane );

        rect = inPane;
    }
}

// helpers

static inline void check_upper_overrun( int& pos, int width, int mousePos )
{
    if ( mousePos >= pos + width )
        pos = mousePos - width/2;
}

static inline void check_lower_overrun( int& pos, int width, int mousePos )
{
    if ( mousePos <= pos )
        pos = mousePos - width/2;
}

void cbBarDragPlugin::StickToPane( cbDockPane* pPane, wxPoint& mousePos )
{
    int wInPane = GetBarWidthInPane ( pPane );
    int hInPane = GetBarHeightInPane( pPane );

    // adjsut hint-rect horizontally (in pane's orientation)

    if ( pPane->IsHorizontal() )
    {
        mHintRect.width  = wInPane;
        mHintRect.height = hInPane;
    }
    else
    {
        mHintRect.height = wInPane;
        mHintRect.width  = hInPane;
    }

    // adjsut hint-rect vertically (in pane's orientation)

    wxRect& bounds = pPane->mBoundsInParent;

    // true, if hint enters the pane through it's lower edge

    bool fromLowerEdge = ( pPane->IsHorizontal() )
                           ? mousePos.y > bounds.y
                           : mousePos.x > bounds.x;

    // NOTE:: about all the below min/max things: they are meant to ensure
    //        that the mouse pointer doesn't overrun (leave) the hint-rectangle
    //        when its dimensions are recalculated upon sticking it to the pane

    if ( pPane->IsHorizontal() && fromLowerEdge )
    {
        int paneBottomEdgeY = bounds.y + bounds.height;

        mHintRect.y = wxMin( paneBottomEdgeY, mousePos.y );

        check_lower_overrun( mHintRect.y, hInPane, mousePos.y );

    }
    else
        if ( pPane->IsHorizontal() && !fromLowerEdge )
        {
            int paneTopEdgeY = bounds.y;

            mHintRect.y = wxMax( paneTopEdgeY - hInPane, mousePos.y - hInPane );

            check_upper_overrun( mHintRect.y, hInPane, mousePos.y );
        }
        else
            if ( !pPane->IsHorizontal() && fromLowerEdge )
            {
                int paneRightEdgeX = bounds.x + bounds.width;

                mHintRect.x = wxMin( paneRightEdgeX, mousePos.x );

                check_lower_overrun( mHintRect.x, hInPane, mousePos.x );
            }
            else
                if ( !pPane->IsHorizontal() && !fromLowerEdge )
                {
                    int paneLeftEdgeX = bounds.x;

                    mHintRect.x = wxMax( paneLeftEdgeX - hInPane, mousePos.x - hInPane );

                    check_upper_overrun( mHintRect.x, hInPane, mousePos.x );
                }

    mMouseInRectX = mousePos.x - mHintRect.x;
    mMouseInRectY = mousePos.y - mHintRect.y;

    mpCurPane = pPane; // memorize pane to which the hint is currently sticked
}

void cbBarDragPlugin::UnstickFromPane( cbDockPane* pPane, wxPoint& mousePos )
{
    // unsticking causes rectangle to get the shape in which
    // dragged control-bar would be when floated

    int newWidth  = mpDraggedBar->mDimInfo.mSizes[wxCBAR_FLOATING].x;
    int newHeight = mpDraggedBar->mDimInfo.mSizes[wxCBAR_FLOATING].y;

    wxRect& flBounds = mpDraggedBar->mDimInfo.mBounds[wxCBAR_FLOATING];

    if ( flBounds.width != -1 )
    {
        newWidth  = flBounds.width;
        newHeight = flBounds.height;
    }

    mHintRect.width  = newWidth;
    mHintRect.height = newHeight;

    wxRect& bounds = pPane->mBoundsInParent;

    // true, if hint leaves the pane through it's lower edge

    bool fromLowerEdge = ( pPane->IsHorizontal() )
                           ? mousePos.y > bounds.y
                           : mousePos.x > bounds.x;

    // NOTE:: ...all the below min/max things - see comments about it in StickToPane(..)

    if ( pPane->IsHorizontal() && fromLowerEdge )
    {
        // bool fromLowerEdge = mousePos.y > bounds.y;

        mHintRect.y = wxMax( bounds.y + bounds.height + 1, mousePos.y - newHeight );

        check_upper_overrun( mHintRect.y, newHeight, mousePos.y );

        // this is how MFC's hint behaves:

        if ( mMouseInRectX > newWidth )
            mHintRect.x = mousePos.x - ( newWidth / 2 );
    }
    else
        if ( pPane->IsHorizontal() && !fromLowerEdge )
        {
            mHintRect.y = wxMin( bounds.y - newHeight - 1, mousePos.y );

            // -/-

            if ( mMouseInRectX > newWidth )
                mHintRect.x = mousePos.x - ( newWidth / 2 );

            check_lower_overrun( mHintRect.y, newHeight, mousePos.y );
        }
        else
            if ( !pPane->IsHorizontal() && fromLowerEdge )
            {
                mHintRect.x = wxMax( bounds.x + bounds.width, mousePos.x - newWidth );

                // -/-

                if ( mMouseInRectY > newHeight )
                    mHintRect.y = mousePos.y - ( newHeight / 2 );

                check_upper_overrun( mHintRect.x, newWidth, mousePos.x );
            }
            else
                if ( !pPane->IsHorizontal() && !fromLowerEdge )
                {
                    mHintRect.x = wxMin( bounds.x - newWidth - 1, mousePos.x );

                    // -/-

                    if ( mMouseInRectY > newHeight )
                        mHintRect.y = mousePos.y - ( newHeight / 2 );

                    check_lower_overrun( mHintRect.x, newWidth, mousePos.x );
                }

    mMouseInRectX = mousePos.x - mHintRect.x;
    mMouseInRectY = mousePos.y - mHintRect.y;

    mpCurPane = NULL;
}

int cbBarDragPlugin::GetBarWidthInPane( cbDockPane* pPane )
{
    if ( pPane == mpSrcPane )
        return mBarWidthInSrcPane;

    // this is how MFC's bars behave:

    if ( pPane->IsHorizontal() )
        return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_HORIZONTALLY].x;
    else
        return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_VERTICALLY  ].x;
}

int cbBarDragPlugin::GetBarHeightInPane( cbDockPane* pPane )
{
    if ( pPane->IsHorizontal() )
        return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_HORIZONTALLY].y;
    else
        return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_VERTICALLY  ].y;
}

void cbBarDragPlugin::ShowHint( bool prevWasInClient )
{
    bool wasDocked = false;

    if ( mpSrcPane->mProps.mRealTimeUpdatesOn == false )
    {
        // do heavy calculations first

        wxRect actualRect = mHintRect; // will be adjusted depending on drag-settings

        if ( mpSrcPane->mProps.mExactDockPredictionOn && mpCurPane )
        {
#ifdef  __WXDEBUG__
            bool success =
#endif
                           mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane, false );

            wxASSERT( success ); // DBG::

            actualRect = mpDraggedBar->mBounds;

            mpCurPane->PaneToFrame( &actualRect );
        }
        else
            CalcOnScreenDims( actualRect );

        // release previous hint

        if ( mPrevHintRect.x != POS_UNDEFINED )
        {
            // erase previous rectangle

            cbDrawHintRectEvent evt( mPrevHintRect, prevWasInClient, true, false );

            mpLayout->FirePluginEvent( evt );
        }

        // draw new hint

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -