Files
wxWidgets/contrib/src/fl/bardragpl.cpp
Julian Smart 879da8c81b Applied recent FL patches from Benjamin Williams <biwilliajsb@yahoo.com>.
1) There is a problem
in that floating frames are not currently supported
with !mRealTimeUpdates.  We wrote a patch to correct
this problem.  You will find it attached to this
posting.

Here is a description of what was changed and why.  In
cbBarDragPlugin::ShowHint(), SetBarState is called
every time mpCurPane changes.  This is correct.
However, this also happens every time, even if
mRealTimeUpdates is false.  The state should not be
changed during the drag operation if mRealTimeUpdates
is off.  This is corrected in this patch.  Code was
also added in cbBarDragPlugin::OnLButtonUp() to
actually do the state changing, only if
mRealTimeUpdates is off.  Normally, this is performed
in ShowHint if mRealTimeUpdates is on.

I also took the liberty of changing the drag cursor
back to an arrow.  This is the way it is in MS Visual
C++, and it looks way better.  The MoveWindow cursor
looks terrible, IMHO.  When FL gets the embedded
cursor code working, we can switch back to a hand or
something else.


2) This time we have
discovered a crash bug in FL.  The steps to reproduce this
bug are as follows:

1. Open up a pane, dock it.
2. Click the Expand button (arrow button) in the
   frame hints portion
3. Click it again to Collapse the pane.
4. Now click the close button of the pane. Crash.

We investigated what was causing this problem, and it turns
out that the button state never gets unset.  Once a button
is pressed, it is always pressed.  Thus, when the expand/
collapse button is pressed, and then the close button is
pressed, the pane will close, but then FL will also try to
expand or collapse the pane as well, because it thinks that
the expand/collapse button was set.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15802 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2002-06-12 08:29:12 +00:00

965 lines
22 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: bardragpl.cpp
// Purpose: cbBarDragPlugin implementation
// Author: Aleksandras Gluchovas
// Modified by:
// Created: 23/09/98
// RCS-ID: $Id$
// Copyright: (c) Aleksandras Gluchovas
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
#pragma implementation "bardragpl.h"
#endif
// 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 )
{
bool success = 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
cbDrawHintRectEvent evt( actualRect, mpCurPane == NULL, FALSE, FALSE );
mpLayout->FirePluginEvent( evt );
mPrevHintRect = actualRect;
}
else
{
// otherwise, if real-time updates option is ON
if ( mpDraggedBar->mState != wxCBAR_FLOATING && !mpCurPane )
{
mpLayout->SetBarState( mpDraggedBar, wxCBAR_FLOATING, TRUE );
}
else
if ( mpDraggedBar->mState == wxCBAR_FLOATING && mpCurPane )
{
mpLayout->SetBarState( mpDraggedBar, wxCBAR_DOCKED_HORIZONTALLY, FALSE );
wasDocked = TRUE;
}
if ( mpCurPane )
{
mpLayout->GetUpdatesManager().OnStartChanges();
if ( wasDocked )
mpDraggedBar->mUMgrData.SetDirty( TRUE );
bool success = mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane, FALSE );
wxASSERT( success ); // DBG ::
mpLayout->GetUpdatesManager().OnFinishChanges();
mpLayout->GetUpdatesManager().UpdateNow();
}
else
{
if ( mpLayout->mFloatingOn )
{
// move the top-most floated bar around as user drags the hint
mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ] = mHintRect;
mpLayout->ApplyBarProperties( mpDraggedBar );
}
}
}
}
/*** event handlers ***/
void cbBarDragPlugin::OnMouseMove( cbMotionEvent& event )
{
// calculate postion in frame's coordiantes
if ( !mBarDragStarted )
{
event.Skip(); // pass event to the next plugin
return;
}
wxPoint mousePos = event.mPos;
event.mpPane->PaneToFrame( &mousePos.x, &mousePos.y );
bool prevIsInClient = ( mpCurPane == 0 );
AdjustHintRect( mousePos );
// if the hint-rect is not "tempted" to any pane yet
if ( mpCurPane == NULL )
{
cbDockPane* pPane = HitTestPanes( mHintRect );
if ( !pPane )
// enable sticking again, if we've left the pane completely
mCanStick = TRUE;
if ( mCanStick && pPane &&
GetDistanceToPane( pPane, mousePos ) < GetBarHeightInPane( pPane ) )
StickToPane( pPane, mousePos );
else
if ( pPane && HitTestPanes( mousePos ) == pPane && 0 ) // FOR NOW:: disabled
StickToPane( pPane, mousePos );
}
else
{
// otherwise, when rect is now sticked to some of the panes
// check if it should still remain in this pane
mCanStick = TRUE;
bool mouseInOther = IsInOtherPane( mousePos );
if ( mouseInOther )
{
cbDockPane* pPane = HitTestPanes( mousePos );
StickToPane( pPane, mousePos );
}
else
{
if ( IsInClientArea( mousePos ) )
{
cbDockPane* pPane = HitTestPanes( mHintRect );
if ( pPane &&
pPane != mpCurPane &&
GetDistanceToPane( pPane, mousePos ) < GetBarHeightInPane( pPane ) )
StickToPane( pPane, mousePos );
else
if ( !pPane )
{
UnstickFromPane( mpCurPane, mousePos );
// FOR NOW:: disabled, would cause some mess
//mCanStick = FALSE; // prevents from sticking to this
// pane again, flag is reset when hint-rect
// leaves the pane completely
}
else
if ( GetDistanceToPane( pPane, mousePos ) > GetBarHeightInPane( pPane ) )
{
if ( !HitsPane( mpCurPane, mHintRect ) )
{
UnstickFromPane( mpCurPane, mousePos );
// FOR NOW:: disabled, would cause some mess
//mCanStick = FALSE; // prevents from sticking to this
// pane again, flag is reset when hint-rect
// leaves the pane completely
}
}
}
else
{
}
}
}
ShowHint( prevIsInClient );
wxCursor* pPrevCurs = mpCurCursor;
if ( mpCurPane )
{
mpCurCursor = mpLayout->mpNormalCursor;
}
else
{
// if floating is off, and we are in the client
// area, the cursor will be invalid, otherwise
// it will be the normal cursor
if (mpLayout->mFloatingOn)
{
mpCurCursor = mpLayout->mpNormalCursor;
}
else
{
mpCurCursor = mpLayout->mpNECursor;
}
}
if ( pPrevCurs != mpCurCursor )
mpLayout->GetParentFrame().SetCursor( *mpCurCursor );
}
void cbBarDragPlugin::OnLButtonDown( cbLeftDownEvent& event )
{
if ( mBarDragStarted )
{
wxMessageBox("DblClick!");
}
event.Skip();
}
void cbBarDragPlugin::OnLButtonUp( cbLeftUpEvent& event )
{
if ( mBarDragStarted )
{
if ( mpSrcPane->mProps.mRealTimeUpdatesOn == FALSE )
{
// erase current rectangle, and finsih on-screen drawing session
cbDrawHintRectEvent evt( mPrevHintRect, mpCurPane == NULL, TRUE, TRUE );
mpLayout->FirePluginEvent( evt );
if ( mpCurPane != NULL )
{
if ( mpSrcPane->mProps.mExactDockPredictionOn )
{
mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane, FALSE );
mpLayout->GetUpdatesManager().OnFinishChanges();
mpLayout->GetUpdatesManager().UpdateNow();
}
else
{
if (mpDraggedBar->mState == wxCBAR_FLOATING)
{
mpLayout->SetBarState( mpDraggedBar, wxCBAR_DOCKED_HORIZONTALLY, TRUE);
}
mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane );
}
}
else
{
if (mpDraggedBar->mState != wxCBAR_FLOATING)
{
mpLayout->SetBarState(mpDraggedBar, wxCBAR_FLOATING, true);
}
mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ] = mHintRect;
mpLayout->ApplyBarProperties( mpDraggedBar );
}
}
mHintRect.width = -1;
// 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
mpLayout->ReleaseEventsFromPane( event.mpPane );
mpLayout->ReleaseEventsFromPlugin( this );
mBarDragStarted = FALSE;
if ( mBarWasFloating && mpDraggedBar->mState != wxCBAR_FLOATING )
{
// save bar's floating position before it was docked
mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ] = mFloatedBarBounds;
}
}
else
event.Skip(); // pass event to the next plugin
}
void cbBarDragPlugin::OnLDblClick( cbLeftDClickEvent& event )
{
int avoidCompilerWarning = 1;
if ( avoidCompilerWarning )
{
cbBarInfo* pHittedBar;
cbRowInfo* pRow;
if ( event.mpPane->HitTestPaneItems( event.mPos, // in pane's coordiantes
&pRow,
&pHittedBar ) == CB_BAR_CONTENT_HITTED
)
{
mpLayout->SetBarState( pHittedBar, wxCBAR_FLOATING, TRUE );
mpLayout->RepositionFloatedBar( pHittedBar );
return; // event is "eaten" by this plugin
}
mBarDragStarted = FALSE;
event.Skip();
}
//wxMessageBox("Hi, dblclick arrived!");
}
void cbBarDragPlugin::OnStartBarDragging( cbStartBarDraggingEvent& event )
{
mpDraggedBar = event.mpBar;
mpSrcPane = event.mpPane;
mpLayout->CaptureEventsForPane( event.mpPane );
mpLayout->CaptureEventsForPlugin( this );
mpLayout->GetParentFrame().SetCursor( *mpLayout->mpNormalCursor );
mBarDragStarted = TRUE;
wxRect inParent = mpDraggedBar->mBounds;
mBarWasFloating = mpDraggedBar->mState == wxCBAR_FLOATING;
if ( mBarWasFloating )
{
inParent = mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ];
mFloatedBarBounds = inParent;
}
else
event.mpPane->PaneToFrame( &inParent );
mHintRect.x = POS_UNDEFINED;
mHintRect.width = inParent.width;
mHintRect.height = inParent.height;
mMouseInRectX = event.mPos.x - inParent.x;
mMouseInRectY = event.mPos.y - inParent.y;
mpSrcPane = event.mpPane;
if ( mpDraggedBar->mState == wxCBAR_FLOATING )
mpCurPane = NULL;
else
mpCurPane = event.mpPane;
mPrevHintRect.x = POS_UNDEFINED;
mCanStick = FALSE; // we're not stuck into any pane now -
// there's nowhere to "stick-twice"
mBarWidthInSrcPane = mpDraggedBar->mDimInfo.mSizes[ mpDraggedBar->mState ].x;
if ( mpSrcPane->mProps.mRealTimeUpdatesOn == FALSE &&
mpSrcPane->mProps.mExactDockPredictionOn )
mpLayout->GetUpdatesManager().OnStartChanges(); // capture initial state of layout
// simulate the first mouse movement
int x = event.mPos.x, y = event.mPos.y;
mpSrcPane->FrameToPane( &x, &y );
cbMotionEvent motionEvt( wxPoint(x,y), event.mpPane );
this->OnMouseMove( motionEvt );
return; // event is "eaten" by this plugin
}
/*** on-screen hint-tracking related methods ***/
void cbBarDragPlugin::OnDrawHintRect( cbDrawHintRectEvent& event )
{
if ( !mpScrDc ) StartTracking();
DoDrawHintRect( event.mRect, event.mIsInClient );
if ( event.mLastTime )
FinishTracking();
}
#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.
// FOR NOW:: static
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
};
void cbBarDragPlugin::StartTracking()
{
mpScrDc = new wxScreenDC;
wxScreenDC::StartDrawingOnTop(&mpLayout->GetParentFrame());
}
void cbBarDragPlugin::DoDrawHintRect( wxRect& rect, bool isInClientRect)
{
wxRect scrRect;
RectToScr( rect, scrRect );
int prevLF = mpScrDc->GetLogicalFunction();
mpScrDc->SetLogicalFunction( wxINVERT );
if ( isInClientRect )
{
// 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 );
mpScrDc->SetPen( mpLayout->mNullPen );
mpScrDc->SetBrush( checkerBrush );
int half = mInClientHintBorder / 2;
mpScrDc->DrawRectangle( scrRect.x - half, scrRect.y - half,
scrRect.width + 2*half, mInClientHintBorder );
mpScrDc->DrawRectangle( scrRect.x - half, scrRect.y + scrRect.height - half,
scrRect.width + 2*half, mInClientHintBorder );
mpScrDc->DrawRectangle( scrRect.x - half, scrRect.y + half - 1,
mInClientHintBorder, scrRect.height - 2*half + 2);
mpScrDc->DrawRectangle( scrRect.x + scrRect.width - half,
scrRect.y + half - 1,
mInClientHintBorder, scrRect.height - 2*half + 2);
mpScrDc->SetBrush( wxNullBrush );
}
else
{
mpScrDc->SetPen( mpLayout->mBlackPen );
mpScrDc->DrawLine( scrRect.x, scrRect.y,
scrRect.x + scrRect.width, scrRect.y );
mpScrDc->DrawLine( scrRect.x, scrRect.y + 1,
scrRect.x, scrRect.y + scrRect.height );
mpScrDc->DrawLine( scrRect.x+1, scrRect.y + scrRect.height,
scrRect.x + scrRect.width, scrRect.y + scrRect.height );
mpScrDc->DrawLine( scrRect.x + scrRect.width , scrRect.y,
scrRect.x + scrRect.width, scrRect.y + scrRect.height + 1);
}
mpScrDc->SetLogicalFunction( prevLF );
}
void cbBarDragPlugin::DrawHintRect ( wxRect& rect, bool isInClientRect)
{
DoDrawHintRect( rect, isInClientRect );
}
void cbBarDragPlugin::EraseHintRect( wxRect& rect, bool isInClientRect)
{
DoDrawHintRect( rect, isInClientRect );
}
void cbBarDragPlugin::FinishTracking()
{
wxScreenDC::EndDrawingOnTop();
delete mpScrDc;
mpScrDc = NULL;
}
void cbBarDragPlugin::RectToScr( wxRect& frameRect, wxRect& scrRect )
{
scrRect = frameRect;
int x = frameRect.x, y = frameRect.y;
mpLayout->GetParentFrame().ClientToScreen( &x, &y );
scrRect.x = x;
scrRect.y = y;
}