📄 panedrawpl.cpp
字号:
/////////////////////////////////////////////////////////////////////////////// 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 + -