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

📄 panedrawpl.cpp

📁 Wxpython Implemented on Windows CE, Source code
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/////////////////////////////////////////////////////////////////////////////
// Name:        panedrawpl.cpp
// Purpose:     cbPaneDrawPlugin implementation.
// Author:      Aleksandras Gluchovas
// Modified by:
// Created:     06/09/98
// RCS-ID:      $Id: panedrawpl.cpp,v 1.10 2005/09/23 12:47:43 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 <math.h>
#include <stdlib.h>

#include "wx/utils.h"     // import wxMin,wxMax macros

#include "wx/fl/panedrawpl.h"

// bitmap bits used by bar-resizing brush

#define _IMG_A  0xAA    // Note: modified from _A to _IMG_A, _A was already defined (cygwin)
#define _IMG_B  0x00    // Note: modified from _B to _IMG_A, _B was already defined (cygwin)
#define _IMG_C  0x55    // Note: modified from _C to _IMG_C, for consistency reasons.
#define _IMG_D  0x00    // Note: modified from _D to _IMG_D, for consistency reasons.

static const unsigned char _gCheckerImg[16] = { _IMG_A,_IMG_B,_IMG_C,_IMG_D,
                                                _IMG_A,_IMG_B,_IMG_C,_IMG_D,
                                                _IMG_A,_IMG_B,_IMG_C,_IMG_D,
                                                _IMG_A,_IMG_B,_IMG_C,_IMG_D
                                              };

// FIXME:: The below code somehow doesn't work - cursors remain unchanged
// Used: controlbar.cpp(1268):    set_cursor_bits( _gHorizCursorImg, bits, 32, 16 );
// Used: controlbar.cpp(1272):    set_cursor_bits( _gVertCursorImg, bits, 32, 16 );
/*
static void set_cursor_bits( const char** img, char* bits, int width, int height )
{
    for( int i = 0; i != (width*height)/8; ++i )
        bits[i] = 0;

    for( int y = 0; y != height; ++y )
    {
        const char* row = img[0];

        for( int x = 0; x != width; ++x )
        {
            int bitNo = y*width + x;

            char value = ( row[x] != '.' ) ? 1 : 0;

            bits[ bitNo / sizeof(char) ] |= 
                ( ( bitNo %sizeof(char) ) << value );
        }

        ++img;
    }
}
*/

/***** Implementation for class cbPaneDrawPlugin *****/

IMPLEMENT_DYNAMIC_CLASS( cbPaneDrawPlugin, cbPluginBase )

BEGIN_EVENT_TABLE( cbPaneDrawPlugin, cbPluginBase )

    EVT_PL_LEFT_DOWN           ( cbPaneDrawPlugin::OnLButtonDown         )
    EVT_PL_LEFT_UP               ( cbPaneDrawPlugin::OnLButtonUp           )
//    EVT_PL_LEFT_DCLICK           ( cbPaneDrawPlugin::OnLDblClick           )
    EVT_PL_RIGHT_UP               ( cbPaneDrawPlugin::OnRButtonUp           )
    EVT_PL_MOTION               ( cbPaneDrawPlugin::OnMouseMove           )


    EVT_PL_DRAW_PANE_BKGROUND  ( cbPaneDrawPlugin::OnDrawPaneBackground  )
    EVT_PL_DRAW_PANE_DECOR     ( cbPaneDrawPlugin::OnDrawPaneDecorations )

    EVT_PL_DRAW_ROW_DECOR      ( cbPaneDrawPlugin::OnDrawRowDecorations  )
    EVT_PL_DRAW_ROW_HANDLES    ( cbPaneDrawPlugin::OnDrawRowHandles      )
    EVT_PL_DRAW_ROW_BKGROUND   ( cbPaneDrawPlugin::OnDrawRowBackground   )

    EVT_PL_SIZE_BAR_WND           ( cbPaneDrawPlugin::OnSizeBarWindow       )
    EVT_PL_DRAW_BAR_DECOR       ( cbPaneDrawPlugin::OnDrawBarDecorations  )
    EVT_PL_DRAW_BAR_HANDLES       ( cbPaneDrawPlugin::OnDrawBarHandles      )

    EVT_PL_START_DRAW_IN_AREA  ( cbPaneDrawPlugin::OnStartDrawInArea     )
    EVT_PL_FINISH_DRAW_IN_AREA ( cbPaneDrawPlugin::OnFinishDrawInArea    )

END_EVENT_TABLE()

cbPaneDrawPlugin::cbPaneDrawPlugin(void)

    : mResizeStarted          ( false ),

      mResizeCursorOn         ( false ),
      mpDraggedBar              ( NULL  ),
      mpResizedRow            ( NULL  ),

      mRowHandleHitted        ( false ),
      mIsUpperHandle          ( false ),
      mBarHandleHitted        ( false ),
      mIsLeftHandle           ( false ),
      mBarContentHitted       ( false ),

      mpClntDc ( NULL ),
      mpPane   ( NULL )
{}

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

    : cbPluginBase( pPanel, paneMask ),
    
      // bar-row resizing state varaibles

      mResizeStarted          ( false ),

      mResizeCursorOn         ( false ),
      mpDraggedBar              ( NULL ),
      mpResizedRow            ( NULL ),

      mRowHandleHitted        ( false ),
      mIsUpperHandle          ( false ),
      mBarHandleHitted        ( false ),
      mIsLeftHandle           ( false ),
      mBarContentHitted       ( false ),

      mpClntDc ( NULL ),
      mpPane   ( NULL )
{}

cbPaneDrawPlugin::~cbPaneDrawPlugin()
{
    // DBG::
    wxASSERT( mpClntDc == NULL );
}

void cbPaneDrawPlugin::DrawDraggedHandle( const wxPoint& pos, cbDockPane& pane )
{
    wxScreenDC dc;
    int ofsX = 0;
    int ofsY = 0;

    wxPoint fpos = pos;
    pane.PaneToFrame( &fpos.x, &fpos.y );

    // short-cut
    int resizeHndSize = pane.mProps.mResizeHandleSize;

    // "Required for X to specify that
    // that we wish to draw on top of all windows
    // - and we optimise by specifying the area
    // for creating the overlap window." --J.S.

    wxScreenDC::StartDrawingOnTop(&mpLayout->GetParentFrame());

    mpLayout->GetParentFrame().ClientToScreen( &ofsX, &ofsY );

    int prevLF = dc.GetLogicalFunction();

    // BUG BUG BUG (wx):: somehow stippled brush works only  
    //                      when the bitmap created on stack, not
    //                      as a member of the class

    wxBitmap checker( (const char*)_gCheckerImg, 8,8 );

    wxBrush checkerBrush( checker );

    dc.SetPen( mpLayout->mNullPen );
    dc.SetBrush( checkerBrush );
    dc.SetLogicalFunction( wxXOR );

    if ( mHandleIsVertical )
    {
        int delta = pos.x - mDragOrigin.x;

        if ( !pane.IsHorizontal() )

            delta = pos.y - mDragOrigin.y;

        int realHndOfs;
        realHndOfs = pane.mBoundsInParent.x + pane.mLeftMargin + mHandleOfs;

        int newX = realHndOfs + delta;

        if ( newX + resizeHndSize > mHandleDragArea.x + mHandleDragArea.width )

            newX = mHandleDragArea.x + mHandleDragArea.width  - 1;

        if ( newX < mHandleDragArea.x ) 

            newX = mHandleDragArea.x;

        mDraggedDelta = newX - realHndOfs;

        dc.DrawRectangle( newX + ofsX, mHandleDragArea.y + ofsY,
                          resizeHndSize + 1,
                          mHandleDragArea.height+1 );
    }
    else
    {
        // otherwise, draw horizontal handle

        int delta = pos.y - mDragOrigin.y;

        if ( !pane.IsHorizontal() )

            delta = pos.x - mDragOrigin.x;

        int realHndOfs;
        realHndOfs = pane.mBoundsInParent.y + pane.mTopMargin + mHandleOfs;

        int newY = realHndOfs + delta;

        if ( newY + resizeHndSize > mHandleDragArea.y + mHandleDragArea.height )

            newY = mHandleDragArea.y + mHandleDragArea.height - 1;

        if ( newY < mHandleDragArea.y ) 

            newY = mHandleDragArea.y;

        mDraggedDelta = newY - realHndOfs;

        dc.DrawRectangle( mHandleDragArea.x + ofsX, newY + ofsY,
                          mHandleDragArea.width + 1,
                          resizeHndSize + 1 );
    }

    dc.SetLogicalFunction( prevLF );

    // "End drawing on top (frees the window used for drawing
    // over the screen)" --J.S.
    wxScreenDC::EndDrawingOnTop();
}

void cbPaneDrawPlugin::OnMouseMove( cbMotionEvent& event ) 
{
    if ( !mResizeStarted )
    {
        // if nothing is started, do hit-tests

        bool prevWasRowHandle = mRowHandleHitted;

        mBarContentHitted = false;
        mBarHandleHitted  = false;
        mRowHandleHitted  = false;

        int testResult =  
            event.mpPane->HitTestPaneItems( event.mPos,        // in pane's coordiantes
                                            &mpResizedRow,
                                            &mpDraggedBar );

        if ( testResult != CB_NO_ITEMS_HITTED )
        {
            if ( testResult == CB_BAR_CONTENT_HITTED )
            {
                // restore cursor, if non of the handles were hit
                if ( mResizeCursorOn )
                {
                    // remove resizing hints

                    mpLayout->ReleaseEventsFromPane( event.mpPane );
                    mpLayout->ReleaseEventsFromPlugin( this );
    
                    mResizeCursorOn = false;

                    mBarContentHitted = true;

                    // In Windows, at least, the frame needs to have a null cursor
                    // else child windows (such as text windows) inherit the cursor
#if 1
                    mpLayout->GetParentFrame().SetCursor( wxNullCursor );
#else
                    mpLayout->GetParentFrame().SetCursor( *mpLayout->mpNormalCursor );
#endif
                }

                // TBD:: fire something like "mouse-over-bar" event

                event.Skip(); // pass event to the next handler in the chain
                return;
            }

            wxCursor* pCurs;

            if ( testResult == CB_UPPER_ROW_HANDLE_HITTED ||
                 testResult == CB_LOWER_ROW_HANDLE_HITTED)
            {
                if ( event.mpPane->IsHorizontal() )

                    pCurs = mpLayout->mpVertCursor;
                else
                    pCurs = mpLayout->mpHorizCursor;

                mRowHandleHitted = true;
                mIsUpperHandle    = ( testResult == CB_UPPER_ROW_HANDLE_HITTED );
            }
            else
            {
                // otherwise, if inter-bar handle was hitted

                if ( event.mpPane->IsHorizontal() )

                    pCurs = mpLayout->mpHorizCursor;
                else
                    pCurs = mpLayout->mpVertCursor;

                mBarHandleHitted = true;
                mIsLeftHandle    = ( testResult == CB_LEFT_BAR_HANDLE_HITTED );
            }

            // avoid setting the same cursor twice

            if ( !mResizeCursorOn || prevWasRowHandle != mRowHandleHitted )
            {
                mpLayout->GetParentFrame().SetCursor( *pCurs );

                if ( !mResizeCursorOn )
                {
                    // caputre if not captured yet
                    mpLayout->CaptureEventsForPane( event.mpPane );
                    mpLayout->CaptureEventsForPlugin( this );
                }
            }

            mResizeCursorOn = true;

            // handled is being dragged now, thus event is "eaten" by this plugin

            return;

        } // end of if (HitTestBarHandles())

        // restore cursor, if non of the handles were hit
        if ( mResizeCursorOn )
        {
            mpLayout->ReleaseEventsFromPane( event.mpPane );
            mpLayout->ReleaseEventsFromPlugin( this );

            // In Windows, at least, the frame needs to have a null cursor
            // else child windows (such as text windows) inherit the cursor
#if 1
            mpLayout->GetParentFrame().SetCursor( wxNullCursor );
#else
            mpLayout->GetParentFrame().SetCursor( *mpLayout->mpNormalCursor );
#endif

            mResizeCursorOn = false;
        }

        event.Skip(); // pass event to the next plugin
    }

    // othewise series of actions, if something has already started

    else
    if ( mResizeStarted )
    {
        // apply xor-mask twice 
        DrawDraggedHandle( mPrevPos,   *event.mpPane );

        // draw handle in the new position
        DrawDraggedHandle( event.mPos, *event.mpPane );
        mPrevPos = event.mPos;

        // handled is dragged, thus event is "eaten" by this plugin
    }
    else
        event.Skip(); // pass event to the next plugin
}

void cbPaneDrawPlugin::OnLDblClick( cbLeftDClickEvent& event )
{
    if ( !mResizeCursorOn )
    {
        cbBarInfo* pBarToFloat;

        if ( event.mpPane->HitTestPaneItems( event.mPos,       // in pane's coordiantes
                                             &mpResizedRow,
                                             &pBarToFloat ) == CB_BAR_CONTENT_HITTED
           )
            {
            return;
            }

        event.Skip();
    }
}

void cbPaneDrawPlugin::OnLButtonDown( cbLeftDownEvent& event ) 
{
    wxASSERT( !mResizeStarted );

    if ( mResizeCursorOn )
    {
        mResizeStarted = true;
        mDragOrigin    = event.mPos;
        
        // setup constraints for the dragging handle

        int from, till;
        mHandleOfs        = 0;
        mHandleIsVertical = false;

        if ( mRowHandleHitted )

            event.mpPane->GetRowResizeRange( mpResizedRow, &from, &till, mIsUpperHandle );
        else
            // otherwise if bar handle was hitted
            event.mpPane->GetBarResizeRange( mpDraggedBar, &from, &till, mIsLeftHandle );
         
        if ( mRowHandleHitted )
        {
            mHandleIsVertical = ( event.mpPane->IsHorizontal() ) ? false : true;

            mHandleDragArea.x      = 0;
            mHandleDragArea.width  = event.mpPane->mPaneWidth;

            mHandleDragArea.y      = from;
            mHandleDragArea.height = till - from;

⌨️ 快捷键说明

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