📄 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 + -